1

Delphi XE2、Indy V10、Windows 7 Pro-しかし、私には一般的な概念上の問題があると思います。

  1. IndyのTCPクライアントは同期的です-ブロッキング呼び出しを使用します。
  2. ただし、アプリケーションの一部は非同期です-TCPを介してデータを送信し、次の場合に応答を待ちます
    A)サードパーティのシリアルポートコンポーネントがシリアルポートからの入力を報告します(非同期のようで、独自のスレッドで実行され、メッセージを投稿しますアプリケーションのメインフォームのWindowsメッセージキューに)および
    B)いくつかのタイマーの1つが期限切れになったとき(非同期でもあります)
  3. 私のアプリケーションによるこれらの非同期イベントの処理では、TCPを介してデータを送信し、次のTCPデータを送信する前に応答を取得するために、ブロッキング呼び出しを行う必要があります。例えば

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

これらは互いに割り込むべきではありませんが、現在は割り込んでいます。

明らかに、私の関数にSendTCpDataは、再入可能な呼び出しを防ぐための何らかのブロックメカニズム、またはキューイングメカニズムが必要です。発信者が結果を知る必要があるとすると、私の最善の解決策はミューテックスですか?SendTCpData問題は、TCPトランザクションが、これらの非同期イベントが呼び出すことができる20行の関数の1行にすぎないことです。

これをわかりやすく説明できたと思います。そうでない場合は、詳細をリクエストしてください。

よろしくお願いします。

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 に答える