我正在尝试Windows重叠的IO,但我似乎无法让它以异步方式工作。我编译并运行下面的程序,但它从不打印任何东西,它只是默默地完成。我读过小读数可能会同步,这就是我故意选择读取512MB的原因。
const DWORD Size = 1<<29; // 512MB
char* Buffer = (char*)malloc(Size);
DWORD BytesRead;
OVERLAPPED Overlapped;
memset(&Overlapped, 0, sizeof(Overlapped));
HANDLE File = CreateFile("BigFile", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED, NULL);
assert(File!=INVALID_HANDLE_VALUE);
DWORD Result = ReadFileEx(File, Buffer, Size, &Overlapped, NULL); // This line takes 150ms according to the debugger
assert(Result);
while(!GetOverlappedResult(File, &Overlapped, &BytesRead, FALSE)) {
printf("Waiting...\n");
}
作为附加信息,我已将代码调入调试器,Overlapped.InternalHigh
值在Size
调用期间更新(与ReadFileEx
的值相同)。
我尝试将malloc
替换为VirtualAlloc
,ReadFileEx
替换为ReadFile
,添加FILE_FLAG_NO_BUFFERING
,并检查{{1}的返回读取后,{}为0,ReadFile
为GetLastError
。我尝试过使用RAMMap查看文件是否在缓存中,但只有96KB存在。
我正在使用8GB RAM运行Windows 10(版本1703)。
答案 0 :(得分:-2)
好的,我的工作正常,感谢@RbMm。
除FILE_FLAG_NO_BUFFERING
标志外,内存分配没有任何变化,使用ReadFile
使其有效。我尝试在SleepEx
之后使用ReadFileEx
,并且它在0处引发了访问冲突,这证明@RbMm认为lpCompletionRoutine
不是可选的而是强制的。 (对我而言,这意味着我将使用ReadFile
,因为我不想要完成例程)
至于为什么花了这么长时间才意识到发生了什么:我太过信任调试器了,显然闯入调试器并没有停止IO进程,这意味着内存仍在OVERLAPPED
内更新结构,这让我觉得事情是瞬间完成的。最重要的是我期望ReadFile
能够快速返回,但如果我尝试读取512MB,它实际上需要20ms,当我请求更少的数量时它会快得多。
感谢大家的建议:)
为了完整起见,这是工作计划:
const DWORD Size = 1<<20;
char* Buffer = (char*)malloc(Size);
DWORD BytesRead;
OVERLAPPED Overlapped;
memset(&Overlapped, 0, sizeof(Overlapped));
HANDLE File = CreateFile("BigFile", GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING|FILE_FLAG_OVERLAPPED, NULL);
assert(File!=INVALID_HANDLE_VALUE);
DWORD Result = ReadFile(File, Buffer, Size, NULL, &Overlapped);
assert(Result==FALSE && GetLastError()==ERROR_IO_PENDING);
while(!GetOverlappedResult(File, &Overlapped, &BytesRead, FALSE)) {
printf("Waiting...\n");
}