Benjamin T Benjamin T - 1 year ago 55
C++ Question

ReadFileEx() completion routine not called

I am writing a class (

PipeReader
) to handle named pipes on Windows. The class uses asynchronous IO to read from the pipe.

So far I have been using the class in a thread without an event loop and I had to wait on the IO to finish using
SleepEx()
and it worked.

Now I have a second thread with an event loop and a second instance of the
PipeReader
class, however the completion routine of the second instance is never called.

Call to
CreateFile()
:

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


Call to
ReadFileEx()
:

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


Code for waiting in thread 1, that works:

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;
}


Code of the event loop in thread 2 where the completion routine is never called:

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);

}


EDIT:



If I replace the calle to
MsgWaitForMultipleObjectsEx()
by :

WaitForSingleObjectEx(m_hwnd, INFINITE, TRUE);


it still doesn't work. However if I use
SleepEx()
in the event loop it works.

Answer Source

this is because m_hwnd not a kernel handle. and WaitForSingleObjectEx fail with WAIT_FAILED and GetLastError return to you ERROR_INVALID_HANDLE - as result thread never enter to alterable wait and APC never executed. you need have another message loop. for example:

  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 ;
    }
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download