【发布时间】:2011-02-02 19:22:58
【问题描述】:
根据 MSDN,ReadFile 可以通过 2 种不同的方式读取数据:同步和异步。
我需要第二个。以下代码演示了OVERLAPPED struct 的用法:
#include <windows.h>
#include <stdio.h>
#include <time.h>
void Read()
{
HANDLE hFile = CreateFileA("c:\\1.avi", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if ( hFile == INVALID_HANDLE_VALUE )
{
printf("Failed to open the file\n");
return;
}
int dataSize = 256 * 1024 * 1024;
char* data = (char*)malloc(dataSize);
memset(data, 0xFF, dataSize);
OVERLAPPED overlapped;
memset(&overlapped, 0, sizeof(overlapped));
printf("reading: %d\n", time(NULL));
BOOL result = ReadFile(hFile, data, dataSize, NULL, &overlapped);
printf("sent: %d\n", time(NULL));
DWORD bytesRead;
result = GetOverlappedResult(hFile, &overlapped, &bytesRead, TRUE); // wait until completion - returns immediately
printf("done: %d\n", time(NULL));
CloseHandle(hFile);
}
int main()
{
Read();
}
在 Windows XP 上的输出是: 阅读:1296651896 发送:1296651896 完成:1296651899
这意味着ReadFile没有阻塞并在同一秒立即返回,而读取过程持续了3秒。这是正常的异步读取。
但在 Windows 7 和 Windows 2008 上,我得到以下结果: 阅读:1296661205 发送:1296661209 完成:1296661209。 这是一种同步读取的行为。
MSDN 说 async ReadFile 有时可以表现为同步(例如,当文件被压缩或加密时)。但是这种情况下的返回值应该是TRUE和GetLastError() == NO_ERROR。
在 Windows 7 上,我得到 FALSE 和 GetLastError() == ERROR_IO_PENDING。所以 WinApi 告诉我这是一个异步调用,但是当我查看测试时发现它不是!
我不是唯一发现此“错误”的人:请阅读 ReadFile MSDN 页面上的评论。
那么解决办法是什么?有人知道吗?丹尼斯发现这种奇怪的行为已经过去了 14 个月。
【问题讨论】:
-
Win7 的文件 I/O 子系统发生了巨大变化。否则这不是问题,当您遵守合同时,您会得到正确的阅读。
-
在哪里可以阅读文档?我做错了什么?
-
去年,我正在调查执行异步 WriteFile 调用并遇到与您相同的问题。 WriteFile 调用将阻塞并返回 PENDING。后续等待 IO 结果也将立即返回。唯一的解决方案是 CreateThread 或 QueueUserWorkItem。 (或者忍受主线程上的性能命中)。我按照下面的建议使用了 BUFFERING 标志。没有骰子。
-
我也试图找到解决这个问题的方法。最终也使用了一个线程。
标签: winapi windows-7 asynchronous