2016-05-16 31 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

相關問題