3

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ます。これは予想される動作ですか?

ありがとう。

4

1 に答える 1

3

GetIoCompletionPort正しく機能するには、aへのnull以外のポインタを指定して、「key」値を次の場所に書き込む必要がありますULONG_PTR

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)最後のパケットまで、次にファイルの残りのサイズまで)。

于 2009-10-22T05:04:24.013 に答える