HasOverlappedIoCompleted()
不适用于以ReadFileEx()
and开头的异步 I/O WriteFileEx()
。底部的代码片段演示了这一点。在此示例中,ReadFileEx()
从没有输入的管道读取,因此读取不会完成。但HasOverlappedIoCompleted()
返回 TRUE。如果我将调用更改为重叠ReadFile()
,HasOverlappedIoCompleted()
则按预期返回 FALSE。
我的问题是:如何在不依赖回调本身的情况下确定带有回调的重叠 I/O 请求是否已完成?在我的应用程序中,APC 可能已排队,但不一定已经运行,因为应用程序可能尚未在警报状态下等待。
谢谢。
(注意 GetOverlappedResult() 没有帮助 - 它也返回 TRUE。)
更多背景知识:在我使用的示例中,ReadFileEx()
因为它很容易演示问题。在我的应用程序中,我WriteFileEx()
在管道实例上反复调用。如果前一个WriteFileEx()
还没有完成,我必须丢弃消息而不是发送它(我在同一个管道实例上不能有多个挂起的写入),但是如果前一个WriteFileEx()
已经完成,那么我必须开始下一个,即使完成回调尚未运行。
编辑:问题场景的描述
- 线程进入警报状态(有一个读取 APC 排队)。
- 读取 APC 开始:它将 WriteFileEx() 排队并设置一个“写入挂起”标志。然后它将 ReadFileEx() 排队。
- 主线程开始工作(不可警报)。
- 排队读取完成。
- 排队的写入完成(在读取之后)。
- 主线程进入警报状态。
- 读取的 APC 在队列中排在第一位,因此首先运行:它查看“写入挂起”标志,并且由于它仍处于设置状态,因此它会放弃写入。事实上,虽然 WriteFileEx()已经完成,但它还没有调用它的 APC,因为 ReadFileEx() 先完成了。
我不想测试我的自定义“写入挂起”标志,而是想从操作系统中找出 WriteFileEx() 是否实际完成,即使 APC 尚未运行。
#include <Windows.h>
#include <stdio.h>
#include <assert.h>
VOID CALLBACK readComplete(DWORD err, DWORD bytes, LPOVERLAPPED ovlp)
{
}
int main(int argc, char *argv[])
{
HANDLE hServer;
OVERLAPPED serverOvlp = { 0 };
HANDLE hClient;
DWORD bytes;
BYTE buffer[16];
BOOL result;
hServer = CreateNamedPipe("\\\\.\\pipe\\testpipe", PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT,
PIPE_UNLIMITED_INSTANCES, 0, 0, 5000, NULL);
serverOvlp.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ConnectNamedPipe(hServer, &serverOvlp);
assert(GetLastError() == ERROR_IO_PENDING);
hClient = CreateFile("\\\\.\\pipe\\testpipe", GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
GetOverlappedResult(hServer, &serverOvlp, &bytes, TRUE);
/* Server starts an overlapped read */
// result = ReadFile(hServer, buffer, sizeof(buffer), &bytes, &serverOvlp);
result = ReadFileEx(hServer, buffer, sizeof(buffer), &serverOvlp, readComplete);
if (HasOverlappedIoCompleted(&serverOvlp))
{
puts("Completed");
}
else
{
puts("Not completed");
}
return EXIT_SUCCESS;
}