Link to home
Start Free TrialLog in
Avatar of pHaze426
pHaze426

asked on

Using CEvent / CWinthread during thread termination

I'm writing a multithreaded MFC application (famous last words, I know).  I have a main dialog based application that uses AfxBeginThread to launch a CWinthread-derived UI thread of my design.  My question relates to how to properly terminate the thread when someone presses the cancel button in the main application dialog.

What I've tried so far is the following:  I created a CEvent member variable within the CWinthread-derived class which I initially set to unsignalled.  I have overridden OnCancel in the main dialog as follows:

CSomethingorother::OnCancel {
   m_pMyThread->PostThreadMessage(WM_BAILOUT, 0, 0);
   WaitForSingleObject(m_pMyThread->m_eEndEvent, INFINITE);
   CDialog::OnCancel();
}

When I catch the WM_BAILOUT message in my thread, I call PostQuitMessage.  Then, in ExitInstance for the thread, I have:

   m_eEndEvent.SetEvent();

This all seems to work just as I expect, but my question is this:  Is there a possibility that after the event is signalled, my thread will finish terminating and get deleted before the calling thread (my dialog app) has a chance to properly "see" the event when it's still valid.  In other words, am I running the risk of some later timing issues having it hang indefinitely?  Is this the correct and thread-safe way to do things?  The documentation for MFC's synchronization classes seems spotty to me and I'm not sure if they have some internal mechanisms for making sure things like this function correctly (in fact, I don't see how it could).

Any help would be greatly appreciated.
ASKER CERTIFIED SOLUTION
Avatar of jkr
jkr
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
jkr makes a great suggestion.

I think you should modify the code, so it's not doing an infinite wait on the thread, and try to do a force kill on the thread if it takes too long.
CSomethingorother::OnCancel {
  const int QtyOfRetries = 9;
  DWORD  result ;
  for(int i = 0;i < QtyOfRetries;++i)
  {
    m_pMyThread->PostThreadMessage(WM_BAILOUT, 0, 0);
    DWORD  result = WaitForSingleObject(m_pMyThread->m_hThread, 60000);
    if (WAIT_TIMEOUT != result) break;
  }
  if (WAIT_TIMEOUT == result)
  {//Force kill the thread
  }
  CDialog::OnCancel();
}

That way your application doesn't hang if one thread hangs.
Avatar of pHaze426
pHaze426

ASKER

Guys,

  This seems like a good methodology as opposed to using CEvent, but assuming I wanted to stick with that.  I'm just unsure how a CEvent could be used in this manner, although it seems to be what they were designed for.  The documentation for WaitForSingleObject suggests that it consumes no CPU time while waiting for the event to occurr.  Does this register some sort of interrupt handler with the system for the event?  If so, that might mean I don't have to worry about it.
The problem with using event is that your thread might be dead already, or maybe it never got kicked off in the first place.
In which case, your application will hang forever if your waiting on an event signal