如何终止线程的运行(C/C++)

如何终止线程的运行(C/C++)
想要终止线程的运行,可以使用以下方法: 
1、线程函数返回(最好使用该方法)。 
2、通过调用ExitThread函数,线程将自行撤消(最好不使用该方法)。 
3、同一个进程或另一个进程中的线程调用TerminateThread函数(应避免使用该方法)。 
4、ExitProcess和TerminateProcess函数也可以用来终止线程的运行(应避免使用该方法)。

下面将详细介绍终止线程运行的方法:1-4,并说明线程终止运行时会出现何种情况:5。 

1、线程函数返回 
始终都应该将线程设计成这样的形式,即当想要线程终止运行时,它们就能够返回。这是确保所有线程资源被正确地清除的唯一办法。 
如果线程能够返回,就可以确保下列事项的实现: 
(1)在线程函数中创建的所有C++对象均将通过它们的撤消函数正确地撤消。 
(2)操作系统将正确地释放线程堆栈使用的内存。 
(3)系统将线程的退出代码(在线程的内核对象中维护)设置为线程函数的返回值。 
(4)系统将递减线程内核对象的使用计数。 

2、ExitThread函数 
可以让线程调用ExitThread函数,以便强制线程终止运行: 
函数原型:
VOID ExitThread(DWORD dwExitCode); 
该函数将终止线程的运行,并导致操作系统清除该线程使用的所有操作系统资源。但是,C++资源(如C++类对象)将不被撤消。由于这个原因,最好从线程函数返回,而不是通过调用ExitThread来返回。 
当然,可以使用ExitThread的dwExitThread参数告诉系统将线程的退出代码设置为什么。ExitThread函数并不返回任何值,因为线程已经终止运行,不能执行更多的代码。 
注意终止线程运行的最佳方法是让它的线程函数返回。但是,如果使用本节介绍的方法,应该知道ExitThread函数是Windows用来撤消线程的函数。如果编写C/C++代码,那么决不应该调用ExitThread。应该使用Visual C++运行期库函数_endthreadex。如果不使用Microsoft的Visual C++编译器,你的编译器供应商有它自己的ExitThread的替代函数。不管这个替代函数是什么,都必须使用。 

3、TerminateThread函数 
调用TerminateThread函数也能够终止线程的运行: 
函数原型:
BOOL TerminateThread( 
  HANDLE hThread, 
  DWORD dwExitCode); 
与ExitThread不同,ExitThread总是撤消调用的线程,而TerminateThread能够撤消任何线程。hThread参数用于标识被终止运行的线程的句柄。当线程终止运行时,它的退出代码成为你作为dwExitCode参数传递的值。同时,线程的内核对象的使用计数也被递减。 
注意TerminateThread函数是异步运行的函数,也就是说,它告诉系统你想要线程终止运行,但是,当函数返回时,不能保证线程被撤消。如果需要确切地知道该线程已经终止运行,必须调用WaitForSingleObject或者类似的函数,传递线程的句柄。 
设计良好的应用程序从来不使用这个函数,因为被终止运行的线程收不到它被撤消的通知。线程不能正确地清除,并且不能防止自己被撤消。 
注意当使用返回或调用ExitThread的方法撤消线程时,该线程的内存堆栈也被撤消。但是,如果使用TerminateThread,那么在拥有线程的进程终止运行之前,系统不撤消该线程的堆栈。Microsoft故意用这种方法来实现TerminateThread。如果其他仍然正在执行的线程要引用强制撤消的线程堆栈上的值,那么其他的线程就会出现访问违规的问题。如果将已经撤消的线程的堆栈留在内存中,那么其他线程就可以继续很好地运行。 
此外,当线程终止运行时, DLL通常接收通知。如果使用TerminateThread 强迫线程终止,DLL就不接收通知,这能阻止适当的清除。

4、在进程终止运行时撤消线程 
ExitProcess和TerminateProcess函数也可以用来终止线程的运行。差别在于这些线程将会使终止运行的进程中的所有线程全部终止运行。另外,由于整个进程已经被关闭,进程使用的所有资源肯定已被清除。这当然包括所有线程的堆栈。这两个函数会导致进程中的剩余线程被强制撤消,就像从每个剩余的线程调用TerminateThread一样。显然,这意味着正确的应用程序清除没有发生,即C++对象撤消函数没有被调用,数据没有转至磁盘等等。 

5、线程终止运行时发生的操作 
当线程终止运行时,会发生下列操作: 
(1)线程拥有的所有用户对象均被释放。在Windows中,大多数对象是由包含创建这些对象的线程的进程拥有的。但是一个线程拥有两个用户对象,即窗口和挂钩。当线程终止运行时,系统会自动撤消任何窗口,并且卸载线程创建的或安装的任何挂钩。其他对象只有在拥有线程的进程终止运行时才被撤消。 
(2)线程的退出代码从STILL_ACTIVE改为传递给ExitThread或TerminateThread的代码。 
(3)线程内核对象的状态变为已通知。 
(4)如果线程是进程中最后一个活动线程,系统也将进程视为已经终止运行。 
(5)线程内核对象的使用计数递减1。 
当一个线程终止运行时,在与它相关联的线程内核对象的所有未结束的引用关闭之前,该内核对象不会自动被释放。 
一旦线程不再运行,系统中就没有别的线程能够处理该线程的句柄。然而别的线程可以调用GetExitcodeThread来检查由hThread标识的线程是否已经终止运行。如果它已经终止运行,则确定它的退出代码: 
函数原型:
BOOL GetExitCodeThread( 
  HANDLE hThread, 
  PDWORD pdwExitCode); 
退出代码的值在pdwExitCode指向的DWORD中返回。如果调用GetExitCodeThread时线程尚未终止运行,该函数就用STILL_ACTIVE标识符(定义为0x103)填入DWORD。如果该函数运行成功,便返回TRUE。

时间: 2024-10-22 16:51:48

如何终止线程的运行(C/C++)的相关文章

解析C/C++中如何终止线程的运行_C 语言

想要终止线程的运行,可以使用以下方法: 1.线程函数返回(最好使用该方法). 2.通过调用ExitThread函数,线程将自行撤消(最好不使用该方法). 3.同一个进程或另一个进程中的线程调用TerminateThread函数(应避免使用该方法). 4.ExitProcess和TerminateProcess函数也可以用来终止线程的运行(应避免使用该方法). 下面将详细介绍终止线程运行的方法:1-4,并说明线程终止运行时会出现何种情况:5. 1.线程函数返回 始终都应该将线程设计成这样的形式,即

c++-如何随时终止C++线程的运行?

问题描述 如何随时终止C++线程的运行? 需要用在工业控制方面. 由于几乎每一句代码都会控制外部设备的运动,所以为了使外部设备能够及时停止运动,操作时可能随时会终止线程的执行. 例如一个工作线程: t1(LPVOID lparam) { while( true ) { move(1); move(2); move(3); move(4); } return 0; } 当我单击停止按钮时,不论t1执行到4步中的哪一步,线程必须停止执行并退出而非等待线程完全执行完毕.停止的位置可能是第一步,可能是第

《C#多线程编程实战(原书第2版)》——1.5 终止线程

1.5 终止线程 本节将讲述如何终止线程的执行. 1.5.1 准备工作 为了学习本节,你需要安装Visual Studio 2015.除此之外无需其他准备.本节的源代码放置在BookSamples\Chapter1\Recipe4目录中. 1.5.2 实现方式 请执行以下步骤来了解如何终止线程的执行: 1.启动Visual Studio 2015.创建一个新的C#控制台应用程序项目. 2.在Program.cs文件中加入以下using指令: 3.在Main方法下面加入以下代码片段: 4.在Mai

Java中终止线程的三种方法_java

Thread.stop, Thread.suspend, Thread.resume 和Runtime.runFinalizersOnExit 这些终止线程运行的方法已经被废弃,使用它们是极端不安全的! 1.线程正常执行完毕,正常结束 也就是让run方法执行完毕,该线程就会正常结束. 但有时候线程是永远无法结束的,比如while(true). 2.监视某些条件,结束线程的不间断运行 需要while()循环在某以特定条件下退出,最直接的办法就是设一个boolean标志,并通过设置这个标志来控制循环

急 终止线程-急! 终止线程不知道怎么回事

问题描述 急! 终止线程不知道怎么回事 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" > 错误提示页面 <table cellSpacing="0" cellPadding="0" width="102%" border="0"> <tr> <td width="25"

当主线程崩溃而其它线程继续运行时发生什么

孤线程模式 症状 治疗和预防措施 总结 参考资料 关于作者 对本文的评价 当主线程崩溃而其它线程继续运行时发生什么? Eric E. Allen(eallen@cs.rice.edu) 博士研究生候选人,Rice 大学 2001 年 8 月 在多线程代码中,使用驱动其它线程所负责的动作的单个主线程是常见的.这个主线程发送消息,通常是通过把它们放到一个队列中,然后其它线程处理这些消息.但是如果主线程抛出一个异常,那么剩余的线程会继续运行,等待更多输入到该队列,导致程序冻结.在诊断 Java 代码的

如何安全终止线程

对于Worker线程,终止线程可以使用线程的退出码作为返回值从线程函数返回. 对于UI线程,因为有消息循环,需要发送一个WM_QUIT消息到线程的消息队列,当线程接收到WM_QUIT消息时退出消息循环.因此,结束线程可以在线程内部调用SDK的PostQuitMessage函数,发送WM_QUIT消息. PostQuitMessage函数的定义如下: void PostQuitMessage(int nExitCode); 其中: nExitCode:线程的退出码. MFC还提供了AfxEndTh

android-在哪个线程中运行 AsyncTask?

问题描述 在哪个线程中运行 AsyncTask? 应用程序的 AlertDialog.Builder(context) 中有下面的代码.问题是在哪个线程中运行呢? final Thread myPrettyOperation = new Thread() { @Override public void run() { //Do some really long operation. } }; class MyPrettyTask extends AsyncTask<Void, Integer,

iOS多线程的初步研究(四、五、六)--NSTimer--NSURLConnection子线程中运行 ---- NSOperation

iOS多线程的初步研究(四)-- NSTimer 理解run loop后,才能彻底理解NSTimer的实现原理,也就是说NSTimer实际上依赖run loop实现的. 先看看NSTimer的两个常用方法: + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo; //生成