How to kill a MFC Thread?

0 votes
asked Feb 26, 2009 by nick

I spawn a thread using AfxBeginThread which is just an infinite while loop:

UINT CMyClass::ThreadProc( LPVOID param )
{
  while (TRUE)
  {
      // do stuff
  }
  return 1;
}

How do I kill off this thread in my class destructor?

I think something like

UINT CMyClass::ThreadProc( LPVOID param )
{
  while (m_bKillThread)
  {
      // do stuff
  }
  return 1;
}

and then set m_bKillThread to FALSE in the destructor. But I still need to wait in the destructor until the thread is dead.

4 Answers

0 votes
answered Jan 26, 2009 by lazin

You must wait, until thread do all stuff.

if(WaitForSingleObject(thread_handle, INFINITE) == WAIT_OBJECT_0) 
    ;//all right
else
    ;//report error

beware using TerminateThread function, this is very dangerous.

0 votes
answered Feb 26, 2009 by brian-r-bondy

Actively killing the thread:

Use the return value of AfxBeginThread (CWinThread*) to get the thread handle (m_hThread) then pass that handle to the TerminateThread Win32 API. This is not a safe way to terminate threads though, so please read on.

Waiting for the thread to finish:

Use the return value of AfxBeginThread (CWinThread*) to get the member m_hThread, then use WaitForSingleObject(p->m_hThread, INFINITE); If this function returns WAIT_OBJECT_0, then the thread is finished. Instead of INFINITE you could also put the number of milliseconds to wait before a timeout happens. In this case WAIT_TIMEOUT will be returned.

Signaling to your thread that it should end:

Before doing the WaitForSingleObject just set some kind of flag that the thread should exit. Then in your main loop of the thread you would check for that bool value and break the infinite loop. In your destructor you would set this flag then do a WaitForSingleObject.

Even better ways:

If you need even more control you can use something like boost conditions.

0 votes
answered Jan 25, 2012 by plan9assembler

BTW, About TerminateThread(), use it this way.

DWORD exit_code= NULL;
if (thread != NULL)
{
    GetExitCodeThread(thread->m_hThread, &exit_code);
    if(exit_code == STILL_ACTIVE)
    {
        ::TerminateThread(thread->m_hThread, 0);
        CloseHandle(thread->m_hThread);
    }
    thread->m_hThread = NULL;
    thread = NULL;
}
0 votes
answered Sep 15, 2017 by zar

First you have to start the thread in a way so MFC doesn't delete the thread object when it's finished, the default setting for MFC thread is to delete itself so you want to turn that off.

   m_thread = AfxBeginThread(ThreadProc, this, THREAD_PRIORITY_NORMAL ,CREATE_SUSPENDED);
   m_thread->m_bAutoDelete = FALSE;
   m_thread->ResumeThread();

Now in the thread, you want a mechanism that the caller thread can send it a signal to end itself. There are multiple ways, one is the WaitForSingleObject to check the status of the signal or another way is to simply send this thread a message to end itself. This is graceful ending rather killing it.

While this thread is ending itself (= exiting the thread function, cleaning up), you can have the main thread wait on it to finish before it exits.

     int wait = 2000 // seconds ( I am waiting for 2 seconds for worker to finish)
     int dwRes = WaitForSingleObject( m_thread->m_hThread, wait);
     switch (dwRes)
     {
     case WAIT_OBJECT_0:
         TRACE( _T("worker thread just finished") ); break;
     case WAIT_TIMEOUT:
         TRACE( _T("timed out, worker thread is still busy") ); break;
     }

Note setting m_bAutoDelete = FALSE above made it possible we still have a valid handle when thread finishes so we can wait on it. The last thing you want to do now is delete the CWinThread object to free its memory (since we took the responsibility to do that).

Welcome to Q&A, where you can ask questions and receive answers from other members of the community.
Website Online Counter

...