2009-08-22 50 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

相关问题