如何终止线程的运行(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。
如何终止线程的运行(C/C++)的更多相关文章
- java线程中断和终止线程运行
ava中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线程 ...
- 《Java并发编程》之线程中断与终止线程运行
Java中启动一个线程很容易,通常情况下我们都是等到任务运行结束后让线程自行停止.但有时需要在任务正在运行时取消他们,使得线程快速结束.对此Java并没有提供任何机制.但是我们可以通过Java提供的线 ...
- Java实现终止线程池中正在运行的定时任务
源于开发 最近项目中遇到了一个新的需求,就是实现一个可以动态添加定时任务的功能.说到这里,有人可能会说简单啊,使用quartz就好了,简单粗暴.然而quartz框架太重了,小项目根本不好操作啊.当然, ...
- C# 在异步中使用HttpWebRequest出现的“正在终止线程”错误的解决方案
最近做接口对接,因需求变化需要用到异步推送信息,就利用委托做了异步. 程序运行过程中时不时出现“正在终止线程”的错误信息,导致两边订单信息不一致,代码如下: byte[] byteData = Enc ...
- Java线程池ThreadPoolExecutor使用和分析(三) - 终止线程池原理
相关文章目录: Java线程池ThreadPoolExecutor使用和分析(一) Java线程池ThreadPoolExecutor使用和分析(二) - execute()原理 Java线程池Thr ...
- C# 使用 CancellationTokenSource 终止线程
http://blog.csdn.net/hezheqiang/article/details/51966511 我们在多线程中通常使用一个 C# 使用 CancellationTokenSource ...
- C# CancellationTokenSource 终止线程 CancellationTokenSource实现对超时任务的取消
C# 使用 CancellationTokenSource 终止线程 使用CancellationTokenSource对象需要与Task对象进行配合使用,Task会对当前运行的状态进行控制(这个不用 ...
- [C#]“正在终止线程”的问题
在C#中启用线程后,如果试图使用Abort方法来终止线程,那么必定会抛出“正在终止线程”的异常,一开始我也想过如何来避免这种异常出现,花了不少气力,但最后发现全是徒劳. 原因是一个正在运行的线程被终止 ...
- tomcat关闭后线程依然运行解决办法
tomcat关闭后线程依然运行解决办法,设置线程为守护线程 守护线程与非守护线程 最近在看多线程的Timer章节,发现运用到了守护线程,感觉Java的基础知识还是需要补充. Java分为两种线程:用户 ...
随机推荐
- 微信小程序制作家庭记账本之六
第六天,自己根据样本代码做的记账本可实现添加账目,删除账目和消费总和,实机可以测试,但是没有域名,别人无法访问.
- Linux服务器---邮件服务openwebmail配置
配置openwebmail 通过修改配置文件openwebmail.conf,实现个性化邮箱定制.用户可以自由的更改邮箱logo.域名.容量 .签名等信息. 1.重定向index,快速打开邮箱.将下面 ...
- UVALive 3295 Counting Triangles
题目链接:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_ ...
- Jmeter压力测试和接口测试
jmeter是apache公司基于java开发的一款开源压力测试工具,体积小,功能全,使用方便,是一个比较轻量级的测试工具,使用起来非常简单.因为jmeter是java开发的,所以运行的时候必须先要安 ...
- The Little Prince-12/13
The Little Prince-12/13 突然发现:这应该是一封情书~ 我那时什么也不懂!我应该根据她的行为,而不是根据她的话来判断她. 她使我的生活芬芳多彩,我真不该离开她跑出来.我本应该猜出 ...
- Eloquent JavaScript #06# class
索引 Notes this Prototype 类 class符号 覆盖派生属性 Maps Symbols iterator接口 Getters, setters, and statics 继承 in ...
- svn钩子
#!/bin/sh #修改为服务编码 export.UTF-8 #Set variable REPOS="$1" REV="$2" #svn安装脚本目录 SVN ...
- 用switch语句根据消费金额计算折扣
最终输出效果: 代码: package com.mingrisoft; import java.util.Scanner; public class ProductPrice { public sta ...
- HashMap的实现原理总结
HashMap基于hashing原理,我们通过put()和get()方法储存和获取对象. 当我们将键值对传递给put()方法时,它调用键对象的hashCode()方法来计算hashcode,让后找到b ...
- RGB颜色对照表
RGB颜色对照表 https://www.cnblogs.com/android100/p/android-rgb-list.html #FFFFFF #FFFFF0 #FFFFE0 ...