1

私はIOCPで遊んでいます。メインスレッドでファイルから非同期にデータを読み取る単純なアプリケーションを作成しようとしています。ただし、ReadFileEx関数でエラー(ERROR_INVALID_PARAMETER)が発生していますが、問題なく実行しているようです。私は何を間違っていますか?これが私のサンプルです:

#include "stdafx.h"
#include <windows.h>
#include <assert.h>
#include <stdint.h>

VOID CALLBACK ReadCb(DWORD dwErrorCode,DWORD dwNumberOfBytesTransfered,LPOVERLAPPED lpOverlapped)
{
    fprintf(stderr,"i was here\n");
}


int _tmain(int argc, _TCHAR* argv[])
{
    HANDLE main_io,file_i;
    HANDLE file_handle;
    DWORD bytes_recvd;
    ULONG_PTR data = 0;
    OVERLAPPED overlapped;
    LPOVERLAPPED poverlapped = &overlapped;
    uint8_t read_data[1024];
    DWORD err;

    main_io = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
    assert(main_io != NULL);

    file_handle = CreateFile(L"test.txt",GENERIC_READ,0,NULL,OPEN_EXISTING,FILE_FLAG_OVERLAPPED, NULL);
    assert(file_handle != INVALID_HANDLE_VALUE);

    file_i = CreateIoCompletionPort(file_handle,main_io,data,0);
    assert(file_i != NULL);

    memset(&overlapped,0,sizeof(OVERLAPPED));

    err = ReadFileEx(file_handle,(LPVOID)read_data,1024,&overlapped,ReadCb);
    fprintf(stderr,"err %d\n",GetLastError());
    assert(err != 0);

    assert(GetQueuedCompletionStatus(file_i,&bytes_recvd,&data,&poverlapped,INFINITE));

    CloseHandle(main_io);
    return 0;
}
4

2 に答える 2

1

「関数が成功した場合、戻り値はゼロ以外です」 - ゼロ以外の戻り値に対して GetLastError() を呼び出さないでください! アサーション違反例外が発生した場合に GetLastError に到達しないように、アサート チェックの後に GetLastError 行を移動します。

于 2012-03-13T13:15:14.723 に答える
0

マーティンが言うように、まずエラー処理を修正してください

const BOOL result = ReadFileEx(...);

const DWORD lastError = GetLastError();

if (lastError != ERROR_SUCCESS)
{
   fprintf(stderr, "err %d\n", lastError);
}

GetLastError()からの成功の戻り値を呼び出すべきではないという彼の仮定について、Martin は間違っていることに注意しReadFileEx()ください。

ReadFileEx を使用する場合、関数が「成功」を返した場合でも、GetLastError をチェックして、「成功」であるが知りたい結果があるかどうかを確認する必要があります。たとえば、ReadFileEx を呼び出したときのバッファ オーバーフローは TRUE を返しますが、GetLastError は ERROR_MORE_DATA でオーバーフローを報告します。関数呼び出しが成功し、警告条件がない場合、GetLastError は ERROR_SUCCESS を返します。

しかし、それはあなたの問題を解決するものではなく、サンプルコードをより正確にするだけです...

問題はReadFileEx()、完了ルーチンを使用して非同期ファイル読み取りを行い、I/O 完了ポートを使用して非同期ファイル読み取りを実行しようとしていることです。そのためには、を使用する必要がありますReadFile()。IOCP がより良いルートであると私が感じる理由と、完了ルーチンが少し厄介な理由については、この回答を参照してください...

したがって、ReadFileEx()呼び出しを呼び出しに変更するだけReadFile()で問題はなくなり、コードは読み取りが完了するとIOCPに完了を通知します...

ReadFile(file_handle,(LPVOID)read_data,1024,&overlapped);

これで完了です。

于 2012-03-14T08:59:46.280 に答える