-1

我正在尝试 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, VirtualAllocwith ReadFileEx, ReadFileadd替换FILE_FLAG_NO_BUFFERING,并检查返回ReadFile0GetLastError是否ERROR_IO_PENDING在读取之后。我尝试使用 RAMMap 来查看文件是否在缓存中,但其中只有 96KB。

我正在运行具有 8GB RAM 的 Windows 10(版本 1703)。

4

1 回答 1

-2

好的,我已经成功了,这一切都归功于@RbMm。

内存分配没有改变任何东西,但FILE_FLAG_NO_BUFFERING标志和使用ReadFile使它工作。我尝试使用SleepExafterReadFileEx并在 0 处引发了访问冲突,这证明了@RbMm 的观点,即lpCompletionRoutine不是可选的而是强制性的。(对我来说,这意味着我要使用ReadFile,因为我不想要完成例程)

至于为什么我花了这么长时间才意识到发生了什么:我太相信调试器了,显然闯入调试器并没有停止 IO 进程,这意味着内存仍在OVERLAPPED结构内部更新,这让我觉得事情是瞬间。最重要的是,我希望ReadFile很快返回,但如果我尝试读取 512MB,它实际上需要 20 毫秒,当我请求较小的量时它会快得多。

谢谢大家的建议:)

为了完整起见,这是工作程序:

  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");
  }
于 2017-05-13T21:28:20.223 回答