【问题标题】:IOCP and ReadFileEx usageIOCP 和 ReadFileEx 的使用
【发布时间】:2012-03-14 16:59:46
【问题描述】:

我在玩 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;
}

【问题讨论】:

  • 你可以使用 OVERLAPPED 重叠 = {};而不是 memset(&overlapped, 0, sizeof(OVERLAPPED));

标签: c++ windows winapi iocp


【解决方案1】:

'如果函数成功,则返回值非零' - 不要调用 GetLastError() 以获得非零返回!在断言检查之后移动 GetLastError 行,以便在发生断言冲突异常时不会到达 GetLastError。

【讨论】:

    【解决方案2】:

    正如 Martin 所说,首先修复你的错误处理

    const BOOL result = ReadFileEx(...);
    
    const DWORD lastError = GetLastError();
    
    if (lastError != ERROR_SUCCESS)
    {
       fprintf(stderr, "err %d\n", lastError);
    }
    

    请注意,Martin 认为您不应该调用 GetLastError() 以获得来自 ReadFileEx() 的成功返回的假设是不正确的,尽管这有点特殊......来自MSDN docs

    使用 ReadFileEx 时,您应该检查 GetLastError,即使 函数返回“成功”以检查条件是 “成功”,但有一些你可能想知道的结果。为了 例如,调用 ReadFileEx 时缓冲区溢出将返回 TRUE, 但是 GetLastError 会用 ERROR_MORE_DATA 报告溢出。如果 函数调用成功且没有警告条件, GetLastError 将返回 ERROR_SUCCESS。

    但这并不能解决您的问题,它只会使您的示例代码更正确...

    问题在于ReadFileEx() 使用完成例程进行异步文件读取,而您正在尝试使用 I/O 完成端口进行异步文件读取。为此,您应该使用ReadFile()。请参阅this answer,了解为什么我认为 IOCP 是更好的选择,以及为什么完成例程有点讨厌......

    因此,只需将您的 ReadFileEx() 调用更改为 ReadFile() 调用,您的问题就会消失,并且代码将在读取完成时将完成发布到 IOCP...

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

    你就完成了。

    【讨论】:

    • 谢谢,就是这样!昨天自己找到的,但由于我是这个网站的新用户,我无法回答我的问题!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-08-10
    • 2018-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-26
    相关资源
    最近更新 更多