第六章(4)终止线程的运行

 

终止线程的运行

若要终止线程的运行,可以使用下面的方法:

线程函数返回(最好使用这种方法)

通过调用ExitThread函数,线程将自行撤消(最好不要使用这种方法)

同一个进程或另一个进程中的线程调用TerminateThread函数(应该避免使用这种方法)

包含线程的进程终止运行(应该避免使用这种方法)

  1. 线程函数返回

始终都应该将线程设计成这样的形式,即当想要线程终止运行时,它们就能够返回。这是确保所有线程资源被正确地清除的唯一办法。

如果线程能够返回,就可以确保下列事项的实现:

在线程函数中创建的所有C + +对象均将通过它们的撤消函数正确地撤消。

操作系统将正确地释放线程堆栈使用的内存。

系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。

系统将递减线程内核对象的使用计数。

  1. ExitThread函数

可以让线程调用ExitThread函数,以便强制线程终止运行:

VOID ExitThread(DWORD dwExitCode);

该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C++资源(如C++类对象)将不被撤消。

ExitThread函数是Windows用来撤消线程的函数。如果编写C/C++代码,应该使用编译环境的运行期函数(Visual C++_ endthreadex)。

  1. TerminateThread函数

BOOL TerminateThreadHANDLE hThread DWORD dwExitCode);

hThread参数用于标识被终止运行的线程的句柄。当线程终止运行时,它的退出代码成为你作为dwExitCode参数传递的值。同时,线程的内核对象的使用计数也被递减。

ExitThread总是撤消调用的线程,而TerminateThread能够撤消任何线程。TerminateThread是异步运行的函数,当函数返回时,不能保证线程被撤消。当使用返回或调用ExitThread的方法撤消线程时,该线程的内存堆栈也被撤消。但 TerminateThread在线程的进程终止运行之前,系统不撤消该线程的堆栈。

设计良好的应用程序从来不使用这个函数, 因为被终止运行的线程收不到它被撤消的通知。线程不能正确地清除,并且不能防止自己被撤消。

  1. 在进程终止运行时撤消线程

由于整个进程已经被关闭,进程使用的所有资源肯定已被清除。这当然包括所有线程的堆栈。这两个函数会导致进程中的剩余线程被强制撤消,这意味着正确的应用程序清除没有发生。

  1. 线程终止运行时发生的操作

当线程终止运行时,会发生下列操作:

线程拥有的所有用户对象均被释放。在 Windows中,大多数对象是由包含创建这些对象的线程的进程拥有的。但是一个线程拥有两个用户对象,即窗口和挂钩。当线程终止运行时,系统会自动撤消任何窗口,并且卸载线程创建的或安装的任何挂钩。其他对象只有在拥有线程的进程终止运行时才被撤消。

线程的退出代码从S T I L L _ A C T I V E改为传递给ExitThreadTerminateThread的代码。

线程内核对象的状态变为已通知。

如果线程是进程中最后一个活动线程,系统也将进程视为已经终止运行。

线程内核对象的使用计数递减1

当一个线程终止运行时,在与它相关联的线程内核对象的所有未结束的引用关闭之前,该

内核对象不会自动被释放。

一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用GetExitCodeThread来检查由h T h r e a d标识的线程是否已经终止运行。

BOOL GetExitCodeThread(HANDLE hThread, PDWORD pdwExitCode);

退出代码的值在pdwExitCode指向的DWORD中返回。如果调用GetExitCodeThread时线程尚未终止运行,该函数就用STILL_ACTIVE标识符(定义为0 x 1 0 3)填入DWORD。如果该函数运行成功,便返回T R U E

原文地址:https://www.cnblogs.com/dyufei/p/2574000.html