I / O完了ポートを使用した非同期操作は、転送された0バイトを返します
-
05-07-2019 - |
質問
I / O完了ポートを使用した非同期操作は、転送された0バイトを返しますが、I / O操作は期待どおりに機能します(読み取りバッファーがいっぱいになります)。
BYTE buffer[1024] = {0};
OVERLAPPED o = {0};
HANDLE file = CreateFile(
_T("hello.txt"),
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL
);
HANDLE completion_port = CreateIoCompletionPort(
file,
NULL,
0,
0
);
ReadFile(
file,
buffer,
1024,
NULL,
&o
);
作業スレッド内:
DWORD numBytes = 0;
LPOVERLAPPED po;
GetQueuedCompletionStatus(
completion_port,
&numBytes,
0,
&po,
INFINITE
);
GetOverlappedResult(file, &o, &numBytes, FALSE);
両方の関数はnumBytesで0バイトを返しますが、 buffer
はいっぱいです。これは予想される動作ですか?
ありがとう。
解決
GetIoCompletionPort
が正常に機能するには、「key」値を書き込むための ULONG_PTR
への非NULLポインターを指定する必要があります。
ULONG_PTR key;
GetQueuedCompletionStatus(
completion_port,
&numBytes,
&key,
&po,
INFINITE
);
GetOverlappedResult
を正常に使用するには、 OVERLAPPED
構造体でイベントハンドルを指定する必要があると思います(いずれの場合も強く推奨):
o.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
あなたがそうだったように2つを連続して呼び出しても、実際にはそれほど成果はありません。どちらも同じことを教えてくれます。ただし、両方を連続して呼び出す場合は、3番目のパラメーターを CreateEvent
からTRUEに変更して、イベントを手動リセットに変更する必要があります。私の推測では、あなたはどちらかを動作させることができるかどうかを確認しようとしていただけです。すべてを考慮して、おそらく GetQueuedCompletionStatus
を使用し、そのままにしておきます。もちろん、通常は一度呼び出すだけで終了するだけではありません。通常はループで呼び出し、読み込んだ現在のバッファーを処理してから、再度 ReadFile
を呼び出して、次のような情報の別のバッファーを読み込みます。
DWORD numBytes;
LPOVERLAPPED po;
while (GetQueuedCompletionStatus(completion_port, &numBytes, &key, &po, INFINITE)) {
std::cout << "\rRead: " << numBytes; // just to show it's set correctly.
process(buffer);
po->offset += sizeof(buffer);
ReadFile(file, buffer, sizeof(buffer), NULL, po);
}
少なくとも私のマシンでの簡単なテストでは、これは正しく読み取られたバイト数を示しました( sizeof(buffer)
最後のパケットまで、次にファイルの残りのサイズ)。