2016-05-16 104 views
1

我有把手,我通过stdinHandle = GetStdHandle(STD_INPUT_HANDLE)了,我有单独的线程执行其代码等:的Win32:如何停止的ReadFile(标准输入|管)

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使用,并触发事件在其他线程, 但对于WaitForMultipleObjects没有提到匿名管道尽可能的投入,再加上我当标准输入连接试图安慰, 它变得无用输入到控制台的第一个字符后(始终没有延迟返回控制), 看起来像我在这种情况下使用ReadConsoleInput,而不是ReadFile

+0

'WaitForMultipleObjects()'可以处理命名或未命名的管道以及控制台。 – wilx

+0

@wilx'WaitForMultipleObjects'以奇怪的方式处理事情,如果运行我的程序的进程将0字节写入“管道”标准输入,然后它返回(在第一次调用之后)'WAIT_OBJECT_0',但是'ReadFile'甚至不能读取1个字节,所以我回到问题提到的问题,我们有'ReadFile'等待输入。 – fghj

+0

那么不要写0字节? – wilx

回答

4

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

从(UN)命名管道读取时,调用ReadFile()使用前PeekNamedPipe()

这将让你真正阅读之前轮询STDIN新的输入,然后你就可以在投票间检查线程终止状态。

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

+0

谢谢,它现在按预期工作。 – fghj

-2

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

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

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

+2

OVERLAPPED IO不能用于控制台,或者我错过了某些东西?例如在CreateFile msdn页面中,有一个关于哪些标志被忽略的控制台的特别注意,并且你不能打开带有重叠标志的stdin。可能是我错过了什么? – fghj

相关问题