Keep Main Thread in waiting state until Worker Thread Completes (VC++)

Multithreading is very useful to allow to execute the piece of code concurrently. There are couple of ways in VC++ to keep Main Thread into wait state until Worker Thread finishes its execution. The following steps contains the other way to achieve this without using any of the VC++ provided Wait functions.

Assume the following:

  • CTestDialog – is the test dialog class which is derived from MFC class CDialog.
  • m_pWinThread – is the member of CTestDialog class and it is CWinThread pointer.
  • m_bStopThread – BOOL public member of CTestDialog class to notify to Worker Thread to exit.
  • SimpleWorkerThread – is the controlling function for Worker Thread.

Step (1): Create the Worker Thread in Suspended state and set m_bAutoDelete to FALSE. This will allow to initialize any Thread related variables before starting the Worker Thread & Worker Thread pointer will not delete automatically after Thread completes. Keep in mind that the Worker Thread needs to be Resumed, because initially it is in Suspended state. See the below code snippet…

CTestDialog::OnInitDialog()
{
  ...
  // -- Create Worker Thread in Suspended state
  m_pWinThread = AfxBeginThread(SimpleWorkerThread, this, 0, 0, CREATE_SUSPENDED, NULL);
  if ( m_pWinThread != NULL )
  {
    m_pWinThread->m_bAutoDelete = FALSE;
    m_pWinThread->ResumeThread();
  }
  ...
}

Step (2): Now the Worker Thread is created and the SimpleWorkerThread function will execute. Let us assume SimpleWorkerThread contains an infinite loop.

Step (3): When click on Close button from the Test Dialog, the application will close the Dialog even though the Worker Thread is running. We should change this behaviour, and keep the Dialog in wait state until Worker Thread completes. Main Thread should notify Worker Thread to terminate before closing the application.

Step (4): For this, maintained the member variable m_bStopThread of CTestDialog class. Initially m_bStopThread is set to FALSE, and it should be set to TRUE whenever Main Thread needs to notify the Worker Thread to exit. See the below code snippet …

m_bStopThread = TRUE;

Step (5): As discussed earlier, SimpleWorkerThread function is using an infinite loop. This function should use m_bStopThread to exit the infinite loop and reset back the value back to FALSE. Why resetting value back to FALSE? Yes. It is required. It will explain in the following sections. See the below code snippet…

unsigned int SimpleWorkerThread(LPVOID pParam)
{
  CTestDialog *pDlg = (CTestDialog *)pParam;
  if ( pDlg == NULL )
    return 0; // Return Error
  BOOL *pbStop = (BOOL *)&pDlg->m_bStopThread;
  if ( pbStop == NULL )
    return 0; // Return Error
  do
  {
    ...
    // -- Exit the loop if CTestDialog::m_bStopThread value is TRUE
    if ( *pbStop == TRUE )
    {
      break;
    }
    ...
  }
  while (1);
  return !(*pbStop = FALSE); // -- Return Success
}

Step (6): Now Worker Thread is Terminated. But how to keep the Main Thread in wait until Worker Thread finishes? Again we should use m_bStopThread member. Main Thread will check whether the value of m_bStopThread value is TRUE or FALSE. If it is TRUE, Main Thread will wait; otherwise it exits. That is the reason SimpleWorkerThread assigned the value FALSE to m_bStopThread.  Worker Thread exits if the value of m_bStopThread is TRUE and Main Thread waits if the value of m_bStopThread is TRUE. See the below code snippet …

void CTestDialog::OnCancel()
{
  ...
  // -- Notify the Worker Thread to exit
  m_bStopThread = TRUE;
  ...
  BOOL bRet = FALSE;
  MSG msg;
  while(m_bStopThread == TRUE)
  {
    bRet = GetMessage(&msg, m_hWnd, 0, 0);
    if ( bRet != -1 )
    {
      TranslateMessage(&msg);
      DispatchMessage(&msg);
    }
  }
  ...
  // -- Delete m_pWinThread
  if ( m_pWinThread != NULL )
  {
    delete m_pWinThread;
    m_pWinThread = NULL;
  }
  ...
  CDialog::OnCancel();
}

It is required to process the messages in message map inside the while loop. Otherwise, the application simply hang.

by Code Steps

Leave a Reply