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);
}

请注意,Martin 关于他的假设是不正确的,即您不应该要求GetLastError()从 中返回成功ReadFileEx(),尽管这有点特殊……来自MSDN 文档

使用 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 回答