Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/157.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 未调用ReadFileEx()完成例程_C++_Windows_Winapi_Asynchronous_Overlapped Io - Fatal编程技术网

C++ 未调用ReadFileEx()完成例程

C++ 未调用ReadFileEx()完成例程,c++,windows,winapi,asynchronous,overlapped-io,C++,Windows,Winapi,Asynchronous,Overlapped Io,我正在编写一个类(PipeReader)来处理Windows上的命名管道。该类使用异步IO从管道中读取 到目前为止,我一直在一个没有事件循环的线程中使用该类,我不得不等待IO完成使用SleepEx(),它成功了 现在我有了一个带有事件循环的第二个线程和PipeReader类的第二个实例,但是从未调用第二个实例的完成例程 调用CreateFile(): 调用ReadFileEx(): 用于在线程1中等待的代码,该代码有效: while (SleepEx(msecs < 0 ? INFINIT

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

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

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

调用
CreateFile()

调用
ReadFileEx()

用于在线程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;
}
编辑: 如果我将
MsgWaitForMultipleObjectsEx()
的调用替换为:

WaitForSingleObjectEx(m_hwnd, INFINITE, TRUE);

它仍然不起作用。但是,如果我在事件循环中使用
SleepEx()
,它会工作。

这是因为
m\u hwnd
不是内核句柄。因此,
WaitForSingleObjectEx
失败,而
WAIT\u失败
GetLastError
返回
ERROR\u INVALID\u句柄
——因此线程永远不会进入可警报的等待,也永远不会执行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 ;
    }

谢谢,这很有效。我有一个错误的想法,那就是我必须等待HWND能够使用
PostMessage()
@BenjaminT()唤醒它。不,你不需要等待HWND(而且不能)。您需要准确地第一次调用
MsgWaitForMultipleObjectsEx
,并且仅当它返回
STATUS\u WAIT\u 0
+n(其中n个句柄计数)时,才需要在循环中调用
PeekMessage
,而它返回true
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);

}
WaitForSingleObjectEx(m_hwnd, INFINITE, TRUE);
  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 ;
    }