如何终止一个MFC线程?

11

我使用 AfxBeginThread 生成一个线程,它只是一个无限循环:

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

如何在我的类析构函数中终止这个线程?

我认为可以使用以下代码:

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

然后在析构函数中将m_bKillThread设置为FALSE。但我仍需要在析构函数中等待线程结束。

4个回答

19

主动终止线程:

使用 AfxBeginThreadCWinThread*)的返回值来获取线程句柄(m_hThread),然后将该句柄传递给 TerminateThread Win32 API。虽然这不是一种安全的终止线程的方法,因此请继续阅读。

等待线程完成:

使用 AfxBeginThreadCWinThread*)的返回值来获取成员变量 m_hThread,然后使用 WaitForSingleObject(p->m_hThread, INFINITE);。如果此函数返回 WAIT_OBJECT_0,则表示线程已经完成。你也可以将 INFINITE 替换为等待超时之前要等待的毫秒数。在这种情况下,将返回 WAIT_TIMEOUT

向线程发出结束信号:

在执行 WaitForSingleObject 之前,设置一个标志,表示线程应该退出。然后在线程的主循环中检查该布尔值并跳出无限循环。在析构函数中设置此标志,然后执行 WaitForSingleObject

更好的方法:

如果需要更多的控制,可以使用类似于 boost 条件 的东西。


6
顺便提一下,关于TerminateThread()函数,使用方式如下。
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;
}

你泄露了,你必须调用:delete thread; 在发出 thread = NULL; 之前。 - ingconti

3

首先,您需要以一种方式启动线程,使MFC在线程完成时不会删除线程对象。 MFC线程的默认设置是删除自身,因此您需要关闭它。

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

现在在线程中,您需要一种机制,使调用线程可以向其发送信号以结束自身。有多种方法,其中一种是使用 WaitForSingleObject 检查信号的状态,另一种方法是简单地向该线程发送消息以结束自身。这是优雅地结束而不是强制结束。
当此线程正在结束自身(即退出线程函数,清理)时,您可以让主线程等待它完成后再退出。
     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;
     }

注意在上面设置 m_bAutoDelete = FALSE 使得当线程结束时我们仍然拥有一个有效的句柄,因此我们可以等待它。现在你不想做的最后一件事是删除 CWinThread 对象以释放其内存(因为我们已经承担了这个责任)。

1

你必须等待,直到线程完成所有任务。

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

注意使用TerminateThread函数,这非常危险。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接