多线程处理:在 MFC 中终止线程

两种正常情况导致线程终止:控制函数退出或线程不允许运行到完成。 如果字处理器使用线程进行后台打印,则打印成功完成后,控制函数将正常终止。 但如果用户需要取消打印,则必须提前终止后台打印线程。 本主题介绍如何实现每种情况,以及如何在线程终止后获取线程的退出代码。

普通线程终止

对于工作线程,普通线程终止很简单:退出控制函数并返回一个表示终止原因的值。 可以使用 AfxEndThread 函数或 return 语句。 通常,0 表示成功完成,但这由你决定。

对于用户界面线程,过程同样简单:从用户界面线程内部调用 Windows SDK 中的 PostQuitMessagePostQuitMessage 唯一采用的参数是线程的退出代码。 至于工作线程,0 通常表示成功完成。

线程提前终止

过早终止线程几乎一样简单:从线程内部调用 AfxEndThread。 将所需退出代码作为唯一参数传递。 这会停止执行线程,解除分配线程的堆栈,拆离附加到线程的所有 DLL,并从内存中删除线程对象。

AfxEndThread 必须从要终止的线程中调用。 如果要从另一个线程终止线程,则必须在两个线程之间设置通信方法。

检索线程的退出代码

若要获取工作线程或用户界面线程的退出代码,请调用 GetExitCodeThread 函数。 有关此函数的信息,请参阅 Windows SDK。 此函数获取线程的句柄(存储在 CWinThread 对象的 m_hThread 数据成员中)和一个 DWORD 的地址。

如果线程仍处于活动状态,GetExitCodeThread 会将 STILL_ACTIVE 放置在提供的 DWORD 地址中;否则,退出代码将放置在此地址中。

检索 CWinThread 对象的退出代码需要执行额外的步骤。 默认情况下,当 CWinThread 线程终止时,线程对象将删除。 这意味着将无法访问 m_hThread 数据成员,因为 CWinThread 对象不再存在。 为避免这种情况,请执行下列操作之一:

  • m_bAutoDelete 数据成员设置为 FALSE。 这样,CWinThread 对象就可以在线程终止后继续存在。 然后,可以在线程终止后访问 m_hThread 数据成员。 但如果使用此方法,则需负责销毁 CWinThread 对象,因为框架不会自动删除该对象。 这是首选方法。

  • 单独存储线程的句柄。 创建线程后,将其 m_hThread 数据成员(使用 ::DuplicateHandle)复制到另一个变量并通过该变量访问它。 这样当终止发生时,对象会自动删除,而你仍然可以找出线程终止的原因。 请注意,复制句柄之前,线程不会终止。 最安全的方法是将 CREATE_SUSPENDED 传递给 AfxBeginThread,存储句柄,然后通过调用 ResumeThread 继续线程。

利用任一方法都能确定 CWinThread 对象终止的原因。

另请参阅

使用 C++ 和 MFC 进行多线程编程
_endthread、_endthreadex
_beginthread、_beginthreadex
ExitThread