1

Delphi XE2、Indy V10、Windows 7 Pro - 但我认为我有一个普遍的概念问题。

  1. Indy 的 TCP 客户端是同步的——它使用阻塞调用。
  2. 但是我的应用程序的某些部分是异步的 - 我想通过 TCP 发送数据并等待响应
    A)第 3 方串行端口组件报告来自串行端口的输入(它似乎是异步的并在它自己的线程中运行,发布消息到我的应用程序的主窗体的 Windows 消息队列)和
    B)当几个计时​​器之一到期时(也是异步的)
  3. 我的应用程序对这些异步事件的处理需要进行阻塞调用以通过 TCP 发送数据并在发送下一个 TCP 数据之前获得响应。例如

    procedure OnSerialPortRxChar(...);
    begin  
      if SendTCpData(...) = 'OK' then ...  
    end;  
    
    procedure OnTimerExpiry(...);  
    begin  
      if SendTCpData(...) = 'OK' then ...  
    end;  
    

这些不应该互相打断,但目前可以。

显然,我的函数SendTCpData需要某种阻塞机制来防止重入调用,或者需要排队机制。鉴于调用者需要知道结果,我最好的解决方案是互斥体吗?问题在于 TCP 事务只是SendTCpData那些异步事件可以调用的 20 行函数中的一行。

我希望我已经解释清楚了。如果没有,请索取更多信息。

非常感谢您的帮助。

4

2 回答 2

1

如果您的串行库是 AsyncPro,我会选择单线程解决方案。给猫剥皮的方法不止一种,我并不是说不能使用多线程解决方案。但是鉴于 AsycPro 事件将在主线程中运行,并且您当前没有在应用程序中使用线程,这可能是最简单的前进方式。

在这个解决方案中,我们使用了重入门和队列。下面是 Delphi 和伪代码的混合。

var
  isInTCP: boolean = False;

function DoSendTCP: boolean;
begin
isInTCP := True;
try
  result := SendTCpData(...) = 'OK'
finally
  isInTCP := False
end
end;

procedure OnSerialPortRxChar(...);
// This is safely re-entrant.
begin  
  repeat
    if isInTCP then
        Push the event onto a queue
      else if DoSendTCP then
        // Calling DoSendTCP may cause re-entry.
        etc...
        ;
    if (queue is empty) or isInTCP then break;
    Pop from head of queue
  until False 
end;  
于 2012-08-15T12:56:47.750 回答
0

您可以使用 TIdAntiFreeze。只需将其放在您的主窗体上。您的呼叫仍将被阻止,但您的 GUI 不会被阻止。不过,您可能希望对您的客户端使用一些超时。

于 2012-08-15T12:54:15.923 回答