2

CancelIo()は、呼び出しスレッドに関連付けられたすべての保留中のI/O 操作をキャンセルすることになっています。私の経験では、CancelIo() は将来のI/O 操作もキャンセルすることがあります。与えられた:

ReadFile(port, buffer, length, &bytesTransferred, overlapped);
  1. CancelIo(port)読み取りの直前に呼び出すGetQueuedCompletionStatus()と、読み取り操作を受け取ることはなく、永久にブロックされます。
  2. CancelIo(port)読み取りの直後に呼び出すと、 GetQueuedCompletionStatus()0 が返されますGetLastError()==ERROR_OPERATION_ABORTED
  3. 私が呼び出しCancelIo(port)、保留中または後続の読み取りがない場合、GetQueuedCompletionStatus()永遠にブロックされます。

ここで重要な点は、 のCancelIo()実行がいつ終了したかを検出する方法がないことです。CancelIo()実行が完了し、さらに読み取り要求を発行しても安全であることを確認するにはどうすればよいですか?

PS: http://osdir.com/ml/lib.boost.asio.user/2008-02/msg00074.htmlおよびhttp://www.boost.org/doc/libs/1_44_0/doc/html/を参照してください。 boost_asio/using.html CancelIo() は実際には使用できないようです。お客様は Windows XP のサポートを必要とする必要があります。私のオプションは何ですか?

:シリアルポートから読んでいます。

4

4 に答える 4

3

CancelIo()正常に動作します。コードを誤解しました。

CancelIo()さらに調査すると、コードは呼び出しに続いReadFile()て timeoutを呼び出していたことが判明しましたINFINITE。リモートエンドが何も送信していないため、完了ポートは読み取りの通知を受けていませんでした。つまり、CancelIo()後続の操作をキャンセルしませんでした。

ここでいくつかの目を見張るようなドキュメントを見つけました:

システムは、必要に応じて操作を同期化する権利を留保しているため、非同期 I/O のコーディングには注意してください。したがって、同期または非同期のいずれかで完了する可能性のある I/O 操作を正しく処理するようにプログラムを作成するのが最善です。サンプル コードは、この考慮事項を示しています。

読み取られるデータがデバイス ドライバーによって既にキャッシュされている場合、デバイス ドライバーは非同期操作を同期的に処理することを選択する可能性があることが判明しました。さらに調査したところ、 whenCancelIo()が呼び出される前ReadFile()に、後者が同期的に返されることがあることがわかりました。ReadFile()後で完了ポートが通知されなかった理由はわかりCancelIo()ませんが、この問題を再現できなくなりました。

ReadFile()完了ポートは、同期か非同期かに関係なく通知されます。

于 2010-10-16T21:30:31.950 に答える
2

待機します (タイムアウトがゼロの可能性があります) overlapped.Handle。操作を完了するかキャンセルするかを設定します。

于 2010-10-13T06:13:03.383 に答える
-1

重複した操作を既に使用している場合、なぜ I/O をキャンセルする必要があるのでしょうか? 実行中の I/O 操作を「キャンセル」するという全体的な概念は、競合が発生しやすく、書き込もうとしている基盤となるデバイス スタックに完全に左右されます実際にこれを実行したいのは、その I/O の完了を待っている別のスレッドのブロックを解除するときだけです。

于 2010-10-13T17:58:46.753 に答える
-1

CancelIo 関数を使用せずに非同期 I/O コードを記述することは可能です。質問は、CancelIO を使用しているシナリオによって異なります。ファイル読み取りスレッドを実装する必要があるとしましょう。スレッド擬似コード:

為に(;;)
{
    ReadFile(ポート、バッファ、長さ、&bytesTransferred、オーバーラップ);
    WaitForMultipleObjects( 重複イベント + 停止イベント);

    if (停止イベントが通知される)
       壊す;

    if (重複したイベントが通知される)
        ReadFile の結果を処理する
}

このようなスレッドは、重複した I/O を使用してファイル (ソケット、ポートなど) を読み取ります。ほとんどの場合、WiatForMultipleObjects 行で待機します。新しいデータが利用可能になるか、停止イベントが通知されると、ウェイクアップします。このスレッドを停止するには、別のスレッドから停止イベントを設定します。CancelIO は使用されません。

于 2010-10-13T06:20:07.033 に答える