未调用ReadFileEx()完成例程

时间:2017-07-26 14:24:57

标签: c++ windows winapi asynchronous overlapped-io

我正在编写一个类(PipeReader)来处理Windows上的命名管道。该类使用异步IO从管道读取。

到目前为止,我一直在没有事件循环的线程中使用该类,我不得不等待IO完成使用SleepEx()并且它有效。

现在我有第二个带有事件循环的线程和PipeReader类的第二个实例,但是从不调用第二个实例的完成例程。

致电CreateFile()

handle = CreateFile(fullServerName,
                         GENERIC_READ | GENERIC_WRITE,
                         0,
                         NULL,
                         OPEN_EXISTING,
                         FILE_FLAG_OVERLAPPED,
                         NULL);

致电ReadFileEx()

BOOL status = ReadFileEx(m_handle, ptr, readSize, &m_overlapped, &PipeReader::readFileCompleted);

在线程1中等待的代码,有效:

while (SleepEx(msecs < 0 ? INFINITE : msecs, TRUE) == WAIT_IO_COMPLETION) {
    if (m_readFinished) // Set to true in the completion routine
        return true;

    msecs = // decrease msecs by the amount elapsed
    if (!msecs)
        break;
}

线程2中事件循环的代码,其中永远不会调用完成例程:

forever()
{
    forever()
    {
        bool haveMessage = PeekMessage(&msg, 0, 0, 0, PM_REMOVE);

        if (haveMessage)
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }
        else
        {
            break; //No message leave loop
        }
    }


    HANDLE handles[1];
    handles[0] = m_hwnd;
    DWORD result = MsgWaitForMultipleObjectsEx(1, handles, INFINITE, QS_ALLINPUT, MWMO_ALERTABLE|MWMO_INPUTAVAILABLE);

}

编辑:

如果我将calle替换为MsgWaitForMultipleObjectsEx()

WaitForSingleObjectEx(m_hwnd, INFINITE, TRUE);

它仍然无法运作。但是,如果我在事件循环中使用SleepEx(),则可以正常工作。

1 个答案:

答案 0 :(得分:3)

这是因为m_hwnd不是内核句柄。所以WaitForSingleObjectEx失败,WAIT_FAILEDGetLastError返回ERROR_INVALID_HANDLE - 因此线程永远不会进入可警告的等待,并且永远不会执行APC。您需要有另一个消息循环,例如:

  for ( ; ; ) {

    MSG msg;

    switch(MsgWaitForMultipleObjectsEx(0, 0, INFINITE, QS_ALLINPUT, MWMO_INPUTAVAILABLE| MWMO_ALERTABLE)) 
    {

    case STATUS_WAIT_0 : 

      while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE)) {

        switch(msg.message) {
        case WM_QUIT: 
          return;
        default: 
          if (!IsDialogMessage(hwnd, &msg))
          {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
          }
      }
    }
    case WAIT_IO_COMPLETION :
    // apc called
    continue;
    default: return ;
    }