2009-08-22 19 views
1

私は最近シリアル通信を行っています。そのため、読み込みや書き込みなどを担当するすべてのWindows API関数に簡単なインターフェイスを提供するクラスを準備しました。このクラスの内部は非同期に処理されます。重複したI/O操作中のシリアルポートと処理エラー

私が質問に行く前に、シリアルポートからデータをどのように書き込んで読み込むのかを教えてください。これは書き込み機能の構造はまったく同じなので、提示機能はありません両方とも)。

function TSerialPort.Read(var pBuffer; const lBufferSize: Cardinal): Cardinal; 
var 
    lOverlapped: OVERLAPPED; 
    lLastError: Cardinal; 
    lEvent: TEvent; 
begin 
    lEvent := TEvent.Create(nil, True, False, ''); 
    try 
    FillChar(lOverlapped, SizeOf(lOverlapped), 0); 
    lOverlapped.hEvent := lEvent.Handle; 

    if not ReadFile(FSerialPortHandle, pBuffer, lBufferSize, Result, @lOverlapped) then 
    begin 
     lLastError := GetLastError; 
     if (lLastError <> ERROR_IO_PENDING) and (lLastError <> ERROR_SUCCESS) then 
     raise Exception.Create(SysErrorMessage(lLastError)); 

     case lEvent.WaitFor(INFINITE) of 
     wrSignaled: 
      if not GetOverlappedResult(FSerialPortHandle, lOverlapped, Result, False) then 
      raise Exception.Create(SysErrorMessage(GetLastError)); 

     wrError: 
      begin 
      lLastError := lEvent.LastError; 
      //this is a call to Windows.CancelIo(FSerialPortHandle); 
      if Self.CancelIO() then 
       lEvent.WaitFor(INFINITE); 
      raise Exception.Create(SysErrorMessage(lLastError)); 
      end; 
     end; 
    end; 
    finally 
    FreeAndNil(lEvent); 
    end; 
end; 

あなたはこの機能を終了する読み出し動作を待っている間、私は重複業務用のシリアルポートを開いて、なぜ、ここで私の説明があります私に尋ねる前に - シリアルポートを開いた場合にのみ、この方法では、私は時間WaitCommEvent()メソッドを指定することができますイベントを待ちます。オーバーラップしない操作のためにポートを開いた場合、WaitCommEvent()はシリアルポートにイベントが表示されるまでブロックされ、必ずしも呼び出しスレッドが永遠にブロックされるわけではありません。

しかし、上記のRead()関数に注目しましょう。

1)まず、イベントを設定するための時間制限なしで待機します。現在のスレッドが何らかの理由で永遠にブロックされる可能性はありますか?イベントが非同期的に読み取り操作を実行するスレッドによって設定されるかどうかを100%確かめることができるかどうかはわかりません。私は、シリアルポートの読み取りタイムアウトがすべて0に設定されていると、指定されたバイト数が読み取られるまで読み取り操作が完了しないことを知っていますが、これは私が認識している動作です。私の質問は、イベントが決して設定されず、WaitFor()メソッドが永遠に待機する原因となる予期しない状況に関係します。起こりそうですか?

2)WaitFor()はwait操作中に何らかのエラーが発生したことを通知するwrErrorを返すことがあります(ただし、重複した読み取り操作とはまったく関係ありません)。したがって、私は、イベントハンドラがもう使用できなくなる可能性があるため、読み込み操作が終了するのを待つ必要はないと思います。 したがって、CancelIO()メソッドを呼び出して読み取り操作をキャンセルし、スレッドによって非同期にキャンセルされた読み取りを実行してから例外を発生させるまで待機します。私はRead()メソッドを直ちに(I/Oをキャンセルせずに)残しておけば、そのスレッドがデータ(重複したレコードデータ)をローカル変数に書き込むことになるので、そのスレッドによって読み込みがキャンセルされるのを待ちます。もはや有効ではない、そうですか? 一方、例外を発生させる前にWaitFor(INFINITE)呼び出しのために現在のスレッドが永久にブロックされる危険性はありますか?

上記の陳述が真であるかどうかを私に教えていただければ幸いです。

は事前にありがとうございました。

答えて

1

奇妙なことに、単に既存のシリアルコンポーネントを使用しないでください。

私はGPSメッセージを受信するためのTurboPower Asyncを使用していますが、自由に利用できる他の人がたくさんあります:http://www.efg2.com/Lab/Library/Delphi/IO/PortIO.htm

それらのほとんどは、すべての下位レベルのIOとスレッドを抽象化、あなたがはるかに高いレベルでシリアル通信を行うことができあなたのためのもの。

あなたは受信するためにonreceiveハンドラを書くだけで、send()に電話をかけて物資を送る必要があります。

+0

ご意見ありがとうございます。あなたは正しいかもしれませんが、私はまだ私の質問に対する答えを知りたいです。それは私の好奇心であり、むしろそのトピックに関する私の知識を広げたいと思っています。 –

関連する問題