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

Multi-threading is very useful to allow to execution of the piece of code concurrently. There are a couple of ways in Visual C++ to keep Main Thread in a wait state until Worker Thread finishes its execution. The following steps contain the other way to achieve this without using any of the VC++ provided Wait functions.

Assume the following:

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

Step (1): Create the Worker Thread in the Suspended state and set m_bAutoDelete to FALSE. This will allow initializing 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 the 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 clicking on the Close button from the Test Dialog, the application will close the Dialog even though the Worker Thread is running. We should change this behavior, and keep the Dialog in a 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 reset the 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 exists. 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 the message map inside the while loop. Otherwise, the application simply hangs.

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

Leave a Reply

Your email address will not be published.

Scroll to top