【问题标题】:win32: how stop ReadFile (stdin|pipe)win32: 如何停止 ReadFile (stdin|pipe)
【发布时间】:2016-05-16 19:35:21
【问题描述】:

我有通过stdinHandle = GetStdHandle(STD_INPUT_HANDLE) 获得的句柄,并且我有执行此类代码的单独线程:

while (!timeToExit) {
  char ch;
  DWORD readBytes = 0;
  if (!::ReadFile(stdinHandle, &ch, sizeof(ch), &readBytes, nullptr)) {
    //report error
    return;
  }
  if (readBytes == 0)
      break;
  //handle new byte
}

其中timeToExitstd::atomic<bool>

我想从另一个线程停止这个线程。我试过这个:

timeToExit = true;
CloseHandle(stdinHandle);

代码挂在CloseHandle

当程序被其他程序运行时,代码挂起 CreatePipeDuplicateHandle 将我的程序的输入重定向到管道。

那么我应该如何以win32方式停止while (!timeToExit)..线程? 或者我应该如何更改while (!timeToExit).. 线程以使其成为可能 阻止它?

更新 在调用ReadFile 之前,我考虑过使用WaitForMultipleObjects stdin 和 event 作为参数,并在其他线程中触发事件, 但是没有提到匿名管道作为WaitForMultipleObjects 的可能输入,而且我在标准输入连接到控制台时尝试过, 并且在第一个字符输入控制台后它变得无用(总是立即返回控制), 看起来在这种情况下我必须使用ReadConsoleInput,而不是ReadFile

【问题讨论】:

  • WaitForMultipleObjects() 可以处理命名或未命名的管道以及控制台。
  • @wilx WaitForMultipleObjects 以奇怪的方式处理事情,如果运行我的程序的进程将 0 字节写入“管道”标准输入,那么它返回(在第一次调用之后)WAIT_OBJECT_0,但 @987654339 @ 甚至无法读取 1 个字节,所以我回到问题中提到的问题,我们有 ReadFile 等待输入。
  • 那么不要写0字节?
  • @wilx 我不能,我的应用程序只能从标准输入读取,运行我的程序的程序是外部应用程序。我有它的源代码,但我怀疑我可以合并它的任何更改。而且它不会写入 0 字节,它会以其他方式导致 WAIT_OBJECT_0 事件,但我仍然不知道如何。可能与我的 x64 构建与 x86 构建的外部程序有关。
  • @wilx if run program from cmd.exe 我得到了相同的结果 - 我没有输入任何内容,但 WaitForMultipleObjects 返回 WAIT_OBJECT_0

标签: c++ winapi


【解决方案1】:

从控制台的实际 STDIN 读取时,您可以使用 PeekConsoleInput()ReadConsoleInfo() 而不是 ReadFile()

从(未)命名管道读取时,请在调用 ReadFile() 之前使用 PeekNamedPipe()

这将允许您在实际读取 STDIN 之前轮询新输入,然后您可以在轮询之间检查线程终止状态。

您可以使用GetFileType() 来检测您的STD_INPUT_HANDLE 手柄上连接了哪种设备。

【讨论】:

    【解决方案2】:

    最简单的解决方案是使用CancelSynchronousIo

    【讨论】:

      【解决方案3】:

      最安全的方法是使用 OVERLAPPED 结构等异步(非阻塞)调用 ReadFile。这可以从您的主线程中完成。

      如果/当您需要取消它时,请调用 CancelIo(来自调用 ReadFile 的同一线程)或 CancelIoEx(如果来自另一个线程)。

      您也许可以使您当前的方法奏效;如果将 timeToExit 标记为 volatile,它可能不会挂起,但这种方法通常会产生更大的问题。

      【讨论】:

      • OVERLAPPED IO 不适用于控制台,或者我错过了什么?例如,在 CreateFile msdn 页面中,控制台有关于忽略哪些标志的特别说明,并且您无法打开带有重叠标志的标准输入。可能我错过了什么?
      猜你喜欢
      • 2016-09-19
      • 2020-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-15
      • 1970-01-01
      • 2012-09-21
      • 2018-01-03
      相关资源
      最近更新 更多