简体   繁体   English

win32:如何停止ReadFile(stdin | pipe)

[英]win32: how stop ReadFile (stdin|pipe)

I have handle that I got via stdinHandle = GetStdHandle(STD_INPUT_HANDLE) and I have separate thread which execute such code: 我有通过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
}

where timeToExit is std::atomic<bool> . 其中timeToExitstd::atomic<bool>

I wan to stop this thread from another thread. 我想从另一个线程停止该线程。 I tried this: 我尝试了这个:

timeToExit = true;
CloseHandle(stdinHandle);

and code hangs in CloseHandle . 并且代码挂在CloseHandle

The code hangs while program is running by other program that uses CreatePipe and DuplicateHandle to redirect input of my program to pipe. 当程序正在运行的其他程序使用CreatePipeDuplicateHandle将我的程序输入重定向到管道时,代码将挂起。

So how should I stop while (!timeToExit).. thread in win32 way? 那么,我该如何以win32方式停止while (!timeToExit)..线程? Or may be I should some how change while (!timeToExit).. thread to make it possible to stop it? 还是我应该while (!timeToExit)..线程中进行一些更改以使其停止?

Update I thought about usage of WaitForMultipleObjects before call of ReadFile with stdin and event as arguments, and trigger event in other thread, but there is no mention of anonymous pipe as possible input for WaitForMultipleObjects , plus I tried when stdin connected to console, and it become useless (always return control without delay) after the first character typed into console, looks like I have to use ReadConsoleInput in this case, instead of ReadFile ? 更新我在以stdin和event作为参数调用ReadFile之前考虑了WaitForMultipleObjects用法,并在其他线程中触发事件,但是没有提到匿名管道作为WaitForMultipleObjects可能输入,加上我在stdin连接到控制台时尝试过,在第一个字符输入到控制台后变得无用(总是无延迟地返回控制),在这种情况下,我不得不使用ReadConsoleInput而不是ReadFile

When reading from a console's actual STDIN, you can use PeekConsoleInput() and ReadConsoleInfo() instead of ReadFile() . 从控制台的实际STDIN读取时,可以使用PeekConsoleInput()ReadConsoleInfo()代替ReadFile()

When reading from an (un)named pipe, use PeekNamedPipe() before calling ReadFile() . 从(未)命名管道读取时,请在调用ReadFile()之前使用PeekNamedPipe() ReadFile()

This will allow you to poll STDIN for new input before actually reading it, and then you can check your thread termination status in between polls. 这将允许您在实际读取STDIN之前轮询STDIN是否有新输入,然后可以在两次轮询之间检查线程终止状态。

You can use GetFileType() to detect what kind of device is attached to your STD_INPUT_HANDLE handle. 您可以使用GetFileType()来检测将哪种设备连接到STD_INPUT_HANDLE句柄。

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

The safest way to do this would be to call ReadFile asynchronously (non-blocking) using the OVERLAPPED structure etc. This can be done from your main thread. 最安全的方法是使用OVERLAPPED结构等异步调用(非阻塞) ReadFile 。这可以从您的主线程完成。

If/when you need to cancel it, call CancelIo (from same thread that called ReadFile) or CancelIoEx (if from another thread). 如果/当您需要取消它时,请调用CancelIo (从与ReadFile相同的线程)或CancelIoEx (如果从另一个线程)。

You might be able to make your current approach work; 您也许可以使当前的方法起作用; if you mark timeToExit as volatile, it may not hang, but that approach commonly creates bigger problems. 如果将timeToExit标记为volatile,它可能不会挂起,但是这种方法通常会带来更大的问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM