2009-08-22 62 views
3

我正在嘗試使用Win32 API來創建一個從STD_INPUT_HANDLE讀取的子線程,並將它讀取的字節推送到套接字中。因爲我希望能夠在退出時安全地關閉此線程,所以我使用ReadFileEx()並重疊了I/O而不是簡單的舊阻塞ReadFile()。這個想法是,我的線程將在WaitForSingleObject()中等待而不是在ReadFile()中等待,並且當主線程想要從線程消失時,它將在該對象上發信號,從線程將喚醒並退出,然後主線程可以繼續其關閉序列。STD_IN_HANDLE塊上的Win32:ReadFileEx(),爲什麼?

我的問題是這樣的:儘管文檔說ReadFileEx()是異步的,因此不會阻塞......我的slave線程仍然在ReadFileEx()內部阻塞。 (我在事件循環中插入printf來驗證它被阻塞的位置)因此,我的主線程不能關閉從屬線程,因此主程序永遠不會退出。

我做錯了什麼,或者是ReadFileEx()意味着從標準輸入讀取時阻止?如果是後者,線程關閉問題的解決方案是什麼?從線程的入口函數低於你的追尋......

[... in the main thread, before the slave thread is spawned...] 
_stdinHandle = GetStdHandle(STD_INPUT_HANDLE); 
_wakeupSignal = CreateEvent(0, false, false, 0); 
[...] 

VOID WINAPI CompletedReadRoutine(DWORD dwErr, DWORD cbBytesRead, LPOVERLAPPED lpOverLap) 
{ 
    printf("CompletedReadRoutine dwErr=%li cbBytesRead=%li overlap=%p\n", dwErr, cbBytesRead, lpOverLap); 
} 

void StdinDataIO :: IOThreadEntry() 
{ 
    char buf[4096]; 
    OVERLAPPED olap; 
    bool keepGoing = true; 
    bool overlappedReadPending = false; 
    while(keepGoing) 
    { 
     if (overlappedReadPending) 
     { 
     DWORD waitResult = WaitForSingleObjectEx(_wakeupSignal, INFINITE, true); 
     switch(waitResult) 
     { 
      case WAIT_IO_COMPLETION: 
      { 
       overlappedReadPending = false; 
       DWORD numBytesRead; 
       if ((GetOverlappedResult(_stdinHandle, &olap, &numBytesRead, true) == false)||(SendData(_slaveSocket, buf, numBytesRead, true) != numBytesRead)) keepGoing = false; 
      } 
      break; 

      default: 
       keepGoing = false; 
      break; 
     } 
     } 
     else 
     { 
     memset(&olap, 0, sizeof(olap)); 
     if (ReadFileEx(_stdinHandle, buf, sizeof(buf), &olap, CompletedReadRoutine)) overlappedReadPending = true; 
                       else keepGoing = false; 
     } 
    } 
    if (overlappedReadPending) CancelIo(_stdinHandle); 
    _slaveSocket.Reset(); // this alerts the main thread that we are gone 
} 

回答

3

ReadFileEx文檔描述,你可以通過什麼樣的文件句柄的:

該文件句柄必須已創建 與FILE_FLAG_OVERLAPPED 標誌並且必須具有GENERIC_READ 訪問權限。

否則,ReadFileEx將在您用未用FILE_FLAG_OVERLAPPED打開的句柄調用時阻塞。

您也可以撥打WaitForSingleObject或由GetStdHandle返回的句柄一些其他的同步功能,並呼籲_kbhit或控制檯事件處理,如果你要確保有可用輸入一些其他的組合。

+0

我很害怕這樣的事情。我不認爲CONIN $技巧會做我想做的事情,因爲我需要不僅能夠從鍵盤讀取,還能夠從父進程或文件重定向中讀取...... – 2009-08-22 04:56:35