代码之家  ›  专栏  ›  技术社区  ›  Aram Hăvărneanu

具有I/O完成端口的异步操作返回传输的0字节

  •  3
  • Aram Hăvărneanu  · 技术社区  · 16 年前

    具有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);
    

    这两个函数都返回0字节(以numBytes为单位),但 buffer

    1 回复  |  直到 16 年前
        1
  •  3
  •   Jerry Coffin    16 年前

    对于 GetIoCompletionPort 要正确工作,您需要指定一个指向 ULONG_PTR

    ULONG_PTR key;
    
    GetQueuedCompletionStatus(
        completion_port,
        &numBytes,
        &key,
        &po,
        INFINITE
    );
    

    使用 GetOverlappedResult 如果成功,我相信您需要在 OVERLAPPED 结构(强烈建议在任何情况下):

    o.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
    

    像你那样连续给两个人打电话并没有什么实际意义——他们都告诉你同样的事情。但是,如果连续调用这两个参数,则需要通过将第三个参数更改为手动重置来将事件更改为手动重置 CreateEvent 这是真的。我的猜测是,你只是想看看你是否能让一个工作。从各方面考虑,我可能只会使用 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) 直到最后一个数据包,然后是文件的剩余大小)。