(MSDN)不断使线程“可更改”而不阻塞线程

时间:2018-07-05 18:01:33

标签: multithreading asynchronous msdn overlapped-io

我正在使用异步过程调用(APC)使用ReadFileEx和WriteFileEx进行重叠的I / O请求。按照MSDN的定义,只有在定义APC的线程处于“可更改”状态时,这些函数的完成例程(APC)才会被处理。

herethere中的示例都使用SleepEx()函数通过执行SleepEx(INFINITE, TRUE)来使线程保持警报状态,以便线程将无限地保持处于警报状态,直到所有APC都处于完成,这意味着线程将被挂起,直到所有APC完成。这不违反我们使用重叠I / O,ReadFileEx和WriteFileEx的原因吗?我认为整个想法是使线程响应并在后台耗时。请帮我解释一下这个想法。

尽管在第一个链接中提到我们可以使用SleepEx(0,TRUE)使线程立即返回并可以同时处理APC,但我仍然不知道在APC之前的那段时间该怎么做返回以及如何知道何时返回。我的目标只是保持线程响应能力,而无所事事。

1 个答案:

答案 0 :(得分:0)

不清楚您在这里要问什么,但我会对此一视同仁。

等待APC是否抵消了进行异步I / O的好处,这完全取决于您的设计。如果您写的是这样的话:

WriteFileEx(..., &overlapped, CompleteWrite);
SleepEx(INFINITE, TRUE);

那么显然,除了使程序过于复杂之外,您还没有完成任何事情。您也可以执行同步I / O。

但是您也可以编写类似的内容:

while (work_to_do)
{
  DoSomeWork();
  WriteFileEx(results);
  SleepEx(0, TRUE);
}

现在,您避免了一些停机时间。如果WriteFileEx需要很长时间才能完成,则线程可以在此期间继续进行工作。

您还可以创建一个服务请求的线程。像这样:

DWORD ThreadProc(...)
{
  while (!done)
  {
    SleepEx(INFINITE, TRUE);
  }
}

该线程只是在等待有人使用QueueUserAPC向其发送命令。如果此类线程发出了I / O,则它可能希望异步执行以允许它在等待I / O完成的同时处理其他命令。 (另一方面,为避免重新进入问题,可能要这样做。)

我希望这能使您了解如何使用这些功能。但是请记住,这些都是非常的旧技术。如果有的话,您很少会在现代程序中使用它们。而是使用CreateThreadPoolIo / StartThreadPoolIo之类的函数让Windows在您专用的工作线程上运行I / O完成。或者更好的方法是使用更高级别的面向任务的库,并避免这些低级的细节。

编辑-在主窗口线程上执行I / O

对此特定问题的简短答案是,不要这样做。在辅助线程上运行I / O,然后使用PostMessageSendMessage将结果发送回主线程。如果由于某种原因您不能执行此操作,则必须使用修改后的消息循环。代替GetMessage,而使用MsgWaitForMultipleObjects,它将使您在等待I / O完成时处理窗口消息。

// error checking omitted
OVERLAPPED overlapped{};
ReadFile(file_handle, buffer, bytes_to_read, &bytes_read, &overlapped);

while (true)
{
  DWORD wait_result = MsgWaitForMultipleObjects(
    1,
    &file_handle,
    FALSE,
    INFINITE,
    QS_ALLINPUT);

  if (wait_result = WAIT_OBJECT_0)
  {
    // I/O completed...
    break;
  }
}