Ara*_*anu 5 c++ windows winapi asynchronous iocp
尽管 I/O 操作按预期工作(我的读取缓冲区已满),但使用 I/O 完成端口的异步操作返回传输的 0 个字节。
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
);
Run Code Online (Sandbox Code Playgroud)
在工作线程中:
DWORD numBytes = 0;
LPOVERLAPPED po;
GetQueuedCompletionStatus(
completion_port,
&numBytes,
0,
&po,
INFINITE
);
GetOverlappedResult(file, &o, &numBytes, FALSE);
Run Code Online (Sandbox Code Playgroud)
这两个函数都返回 numBytes 中的 0 个字节,但buffer正在填充。这是预期的行为吗?
谢谢。
为了GetIoCompletionPort正确工作,您需要指定一个指向 a 的非空指针,ULONG_PTR以便将“key”值写入:
ULONG_PTR key;
GetQueuedCompletionStatus(
completion_port,
&numBytes,
&key,
&po,
INFINITE
);
Run Code Online (Sandbox Code Playgroud)
要成功使用GetOverlappedResult,我相信您需要在结构中指定一个事件句柄OVERLAPPED(在任何情况下强烈建议):
o.hEvent = CreateEvent(NULL, FALSE, TRUE, NULL);
Run Code Online (Sandbox Code Playgroud)
像以前那样连续调用这两个方法并没有多大作用——它们都告诉你同样的事情。不过,如果您连续调用两者,则需要通过将第三个参数更改为CreateEventTRUE 将事件更改为手动重置。我的猜测是,您只是尝试两者,看看是否可以让其中一个工作。考虑到所有因素,我可能只会使用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);
}
Run Code Online (Sandbox Code Playgroud)
至少在我的机器上进行的快速测试中,这显示了正确读取的字节数(sizeof(buffer)直到最后一个数据包,然后是文件的剩余大小)。