Click here to Skip to main content
12,955,118 members (60,067 online)
Click here to Skip to main content
Add your own
alternative version


18 bookmarked
Posted 2 May 2004

SafeThread - A deadlock free worker thread

, 2 May 2004
Rate this:
Please Sign up or sign in to vote.
An article on a simple way to call User Interface methods from a worker thread, avoiding a common deadlock situation


This article describes a method for preventing a deadlock that worker threads cause when calling User Interface methods. A deadlock occurs when the parent window thread is waiting for the worker thread to complete, while the worker thread is waiting for the parent window thread to handle its blocking User Interface call.


The user should have a prior knowledge of multi-threading programming in Windows.

Implementation details

The implementation (below) waits for the thread to complete. When a user interface message is in the message queue it is being handled, in order to avoid the deadlock described above.

  WaitResult = MsgWaitForMultipleObjects(1,     
    // only 1 wait object
                     m_hThread, // worker thread
                     FALSE,   // stop if any
                     INFINITE,  // no timeout
  if (WaitResult == WAIT_OBJECT_0 +1) 
  // Handle windows message
  MSG Msg;
  BOOL IsMessage = ::PeekMessage( Msg,NULL,0,0,PM_REMOVE);
  if (IsMessage) 
} while (WaitResult == WAIT_OBJECT_0+1); 
ASSERT(WaitResult == WAIT_OBJECT_0);

Now, lets add another twist. Sometimes the parent user interface window would like to abort the thread immediately, and yet without any memory leaks. The implementation of the abort method raises a flag. The worker thread must call CheckAborted() periodically to check this flag.
The cleanest way to avoid memory leaks is by throwing an exception. The exception throwing mechanism cleanly destructs the objects in the stack. Objects allocated using the new operator are deleted in the destructor (of one of the objects in the stack) or by a Smart Pointer. You should not worry about catching the exception. CSafeThread has a wrapper of the thread procedure that catches this exception for you.
void CSafeThread::CheckAborted(DWORD WaitTime /* 
= 0 */)
  if (GetCurrentThread()!=NULL &&
     GetCurrentThread()->m_AbortEvent.m_hObject,WaitTime) == WAIT_OBJECT_0)
  THROW(new CSafeThreadAbortException());

The worker thread must also check the abort flag while it Sleeps or Waits. An implementation of WaitForSingleObject() and Sleep(), does just that. Below is the implementation of WaitForSingleObject().
 DWORD CSafeThread::WaitForSingleObject(HANDLE hHandle,
                     DWORD dwMilliseconds)
  CSafeThread* pThis = GetCurrentThread();
  if (pThis == NULL)
  return ::WaitForSingleObject(hHandle,dwMilliseconds);

  HANDLE Handles[2];
  Handles[0] = hHandle; 
  Handles[1] = m_AbortEvent.m_hObject; 
  DWORD WaitResult = ::WaitForMultipleObjects(2,
                        FALSE /* Wait Any */,
  if (WaitResult == WAIT_OBJECT_0 + 1)
  THROW(new CSafeThreadAbortException());
  return WaitResult; 

In addition the CSafeThread implementation stores the handle of the parent window and provides an implementation to MessageBox. Calling this static method ensures that the parent window will be disabled when the message box appears.

Using the code

The example counts down from 10 to 0, displays a message box, and closes the dialog box. In order to start a new safe thread use the supplied BeginSafeThread static method. If you are going to use the MessageBox static method, do not forget to supply the last parent window argument. In the header file, you may use the SP_SafeThread tyepdef (SP stands for Smart Pointer) that will automatically delete the thread object when the dialog box is deleted. The SmartPtr class implementation was written by Sandu Turcan.

m_pThread =  CSafeThread::BeginSafeThread(CountThread, 
  //Thread Proc
                      this,    //Parameter
                      THREAD_PRIORITY_NORMAL, // Priority
                      0, // Stack Size
                      0, // Create Flags
                      0, // Security
                      this // Parent Window);

The implementation uses a helper static method that converts the parameter to this and calls the Count() method. The implementation of Count() changes the value of m_Counter (an MFC static text control) every one second.

UINT CSafeThreadExampleDlg::CountThread(void* pParam)
  CSafeThreadExampleDlg* pThis = 
    reinterpret_cast<CSafeThreadExampleDlg> (pParam);  
  return 0; 

void CSafeThreadExampleDlg::Count() 
  for (int i =10 ; i >=0 ; i--)
  CString si;
  CSafeThread::MessageBox("Countdown complete", // Message
              "SafeThreadExample"); // Title
  EndDialog(IDOK); //close dialog

The user interface of the example includes two buttons. The first one waits until the countdown completes, and the second one aborts the count down.

void CSafeThreadExampleDlg::OnBnClickedShutdown()
  OnOK(); //close dialog

void CSafeThreadExampleDlg::OnBnClickedAbort() 
  OnOK(); //close dialog 

Points of Interest

I am not sure that Microsoft MFC supports the workaround presented in this article. It worked for my project, and I would like to know here if it works also for you :)


This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


About the Author

Software Developer
Israel Israel
No Biography provided

You may also be interested in...

Comments and Discussions

Generalabout dialog memory leaks Pin
Member 365370720-Aug-08 20:14
memberMember 365370720-Aug-08 20:14 
GeneralPlease help Me Pin
Anonymous1-Feb-05 9:56
sussAnonymous1-Feb-05 9:56 
GeneralThank you Pin
Adrian ~ FoobarSoftware.com29-Nov-04 4:55
sussAdrian ~ FoobarSoftware.com29-Nov-04 4:55 
Generalminor points Pin
Anonymous5-May-04 7:51
sussAnonymous5-May-04 7:51 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.170525.1 | Last Updated 3 May 2004
Article Copyright 2004 by itaifrenkel
Everything else Copyright © CodeProject, 1999-2017
Layout: fixed | fluid