winapi - ReadFile 在 Win7 和 Win2k8 上不能异步工作

标签 winapi windows-7 asynchronous

根据 MSDN,ReadFile可以通过两种不同的方式读取数据:同步和异步。
我需要第二个。以下代码演示了 OVERLAPPED 的用法结构:

#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 说异步 ReadFile有时可以表现为同步(例如,当文件被压缩或加密时)。但是这种情况下的返回值应该是TRUE和GetLastError() == NO_ERROR。
在 Windows 7 上我得到 FALSE 和 GetLastError() == ERROR_IO_PENDING。所以 WinApi 告诉我这是一个异步调用,但是当我查看测试时我发现它不是!

我不是唯一发现这个“错误”的人:阅读 ReadFile MSDN 页面上的评论。

那么有什么解决办法呢?有人知道吗?丹尼斯发现这种奇怪的行为已经过去了 14 个月。

最佳答案

我不知道“c:\1.avi”文件的大小,但您提供给 Windows 的缓冲区大小(256M!)可能足以容纳该文件。所以windows决定读取整个文件并按照它喜欢的方式把它放在缓冲区中。您不会对 Windows 说“我想要异步”,而是说“我知道如何处理异步”。

只需将缓冲区大小更改为 1024,您的程序的行为就会完全相同,但仅读取 1024 字节(并返回 ERROR_IO_PENDING)。

一般来说,你做异步是因为你想在操作过程中做一些其他的事情。在此处查看示例:Testing for the End of a File ,因为它演示了异步 ReadFile。如果您更改样本的缓冲区并将其设置为一个大值,它的行为应该与您的完全一样。

PS:我建议你不要依赖时间样本来检查事情,使用返回码和事件

关于winapi - ReadFile 在 Win7 和 Win2k8 上不能异步工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4878868/

相关文章:

c++ - 我如何使用他的 HWND 检查窗口是否有可见的滚动条?

c++ - 调用 API 函数时出现 ESP 错误?

windows - CMD - 等待并行命令行完成?

java - Windows 7 命令提示符 : Typing android. bat 返回 java.exe 选项

c# - 希望通过异步调用提高我的 WebService 的速度,但不确定如何

c# - 如何获取avicap32.dll中已连接的网络摄像头列表?

Windows 7 上 IE 9 中的 HTML 5 Canvas 性能

javascript - 如何让 .each() 等待每次迭代完成

javascript - 为什么这个 async/await 函数返回一个 promise ?

c++ - Win32 MD5 哈希器的奇怪行为