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 正在填充。这是预期的行为吗?

感谢。

有帮助吗?

解决方案

要使 GetIoCompletionPort 正常工作,您需要指定一个指向 ULONG_PTR 的非空指针,以便将'key'值写入:

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)直到最后一个数据包,然后是文件的剩余大小)。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top