oro777
oro777

Reputation: 1110

How to use WaitForSingleObject()

I read different topics concerning the use of WaitForSingleObject() but I still don't understand why I cannot make it work. I have a progress bar which updates using AfxBeginThread and I would like to wait to finish its work before doing another proccess. My code is based on this example: http://www.codeproject.com/Articles/2459/Using-AfxBeginThread-with-class-member-controlling

startupEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL);
THREADSTRUCT *_param = new THREADSTRUCT;
_param->_this = this;
CWinThread* thread = AfxBeginThread (StartThread, _param);
WaitForSingleObject(startupEvent , INFINITE);
AfxMessageBox(_T("This message should pop up after the thread terminates."));

I have defined the startupEvent variable in the header file like this:

protected:
   HANDLE startupEvent;

Here is the thread method.

UINT CView::StartThread (LPVOID param)
{
   THREADSTRUCT* ts = (THREADSTRUCT*)param;
   ::SetEvent(ts->_this->startupEvent);
   //Some heavy calculation from here + ProgressBar update
   return 1;
}

In the above example, I would like the MessageBox to appear after the thread terminate the proccess but it currently appears before.

Upvotes: 1

Views: 3824

Answers (1)

huysentruitw
huysentruitw

Reputation: 28091

Short answer to your question: you need to call ::SetEvent(ts->_this->startupEvent);, after the heavy calculation, otherwise WaitForSingleObject will return before the heavy calculation starts.

Side note: you can use WaitForSingleObject directly on the thread handle, so you don't need an additional event. Like: WaitForSingleObject(thread->m_hThread, INFINITE);

Bad practices

Your solution contains 2 bad practices:

  1. It's a bad idea to block your main-thread, because it runs the main message loop, which in turn is responsible for redrawing GUI elements (like updating the progressbar in your case). Letting the main-thread wait for a worker thread to finish defeats the reason for offloading the heavy calculation to a secondary thread.

  2. Don't touch the GUI from a worker thread. The worker thread can use SendMessage or PostMessage to send status messages to the main thread, which in turn will update the UI. I found an old but still relevant article about this matter.

Upvotes: 3

Related Questions