C#如何优雅的结束线程
作者:宏宇 发布时间:2022-07-27 19:45:27
大家都知道在C#里面,我们可以使用Thread.Start方法来启动一个线程,当我们想停止执行的线程时可以使用Thread.Abort方法来强制停止正在执行的线程,但是请注意,你确定调用了Thread.Abort方法后线程就立刻停止了吗?答案是:不是!
下面我们来解释一下Abort方法是如何工作的。因为公用语言运行时管理了所有的托管的线程,同样它能在每个线程内抛出异常。Abort方法能在目标线程中抛出一个ThreadAbortException异常从而导致目标线程的终止。不过Abort方法被调用后,目标线程可能并不是马上就终止了。因为只要目标线程正在调用非托管的代码而且还没有返回的话,该线程就不会立即终止。而如果目标线程在调用非托管的代码而且陷入了一个死循环的话,该目标线程就根本不会终止。不过这种情况只是一些特例,更多的情况是目标线程在调用托管的代码,一旦Abort被调用那么该线程就立即终止了。
其实一个线程在运行时,我们可以通过Thread.ThreadState属性读出它的状态,正在运行的线程状态就是ThreadState.Running。然后如果我们想强制停止正在执行的线程,就会调用Thread.Abort方法,但是Thread.Abort方法做的事情只是在线程上抛出了一个ThreadAbortException异常,然后将线程的状态置为ThreadState.AbortRequested,MSDN对AbortRequested状态的解释是:已对线程调用了 Thread.Abort 方法,但线程尚未收到试图终止它的挂起的System.Threading.ThreadAbortException,也就是说线程在ThreadState.AbortRequested状态时表示即将结束但是还没有真正结束。可是Thread.Abort方法将线程的状态置为ThreadState.AbortRequested后就立马返回了,而线程真正结束后的状态应该是ThreadState.Aborted,所以一定要注意在调用了Thread.Abort方法后,要记得循环检查Thread.ThreadState属性的值或者调用Thread.Join方法来确保被终止线程已经真正停止,只有当Thread.ThreadState属性为Aborted或Thread.Join方法返回时,才表示线程真正结束了。
下面我就写一个示例代码来说明在调用Thread.Abort方法后,怎样保证线程停止后代码才会继续执行
var thread = new Thread(
new ThreadStart(
() =>
{
while (true)
{
//该线程会进行无限循环,自己不会结束
Thread.Sleep(100);
}
}));
thread.IsBackground = true;
thread.Start();//启动线程
thread.Abort();//调用Thread.Abort方法试图强制终止thread线程
//上面调用Thread.Abort方法后线程thread不一定马上就被终止了,所以我们在这里写了个循环来做检查,看线程thread是否已经真正停止。其实也可以在这里使用Thread.Join方法来等待线程thread终止,Thread.Join方法做的事情和我们在这里写的循环效果是一样的,都是阻塞主线程直到thread线程终止为止
while (thread.ThreadState!=ThreadState.Aborted)
{
//当调用Abort方法后,如果thread线程的状态不为Aborted,主线程就一直在这里做循环,直到thread线程的状态变为Aborted为止
Thread.Sleep(100);
}
//当跳出上面的循环后就表示我们启动的线程thread已经完全终止了
var thread = new Thread(
new ThreadStart(
() =>
{
while (true)
{
//该线程会进行无限循环,自己不会结束
Thread.Sleep(100);
}
}));
thread.IsBackground = true;
thread.Start();//启动线程
thread.Abort();//调用Thread.Abort方法试图强制终止thread线程
//上面调用Thread.Abort方法后线程thread不一定马上就被终止了,所以我们在这里写了个循环来做检查,看线程thread是否已经真正停止。其实也可以在这里使用Thread.Join方法来等待线程thread终止,Thread.Join方法做的事情和我们在这里写的循环效果是一样的,都是阻塞主线程直到thread线程终止为止
while (thread.ThreadState!=ThreadState.Aborted)
{
//当调用Abort方法后,如果thread线程的状态不为Aborted,主线程就一直在这里做循环,直到thread线程的状态变为Aborted为止
Thread.Sleep(100);
}
//当跳出上面的循环后就表示我们启动的线程thread已经完全终止了
不过请记住使用Thread.Abort方法来终止正在执行的线程并不是一个好的方法,因为Abort方法是通过在线程上抛异常来终止线程的,这样可能会产生一些意想不到的问题。最好的办法是在启动的线程中加信号灯,当想要终止线程执行时就更改信号灯的状态,启动的线程当读到信号灯状态改变后自己结束代码的执行,这才是最安全的做法。
将一个信号灯标志位置位true,然后就等待这个线程顺利结束:
USBOP.ThreadStopFlg = true;
while ((USBReadThread.ThreadState != System.Threading.ThreadState.Stopped) && (USBReadThread.ThreadState != System.Threading.ThreadState.Aborted))
{
Thread.Sleep(10);
}
USBOP.ThreadStopFlg = true;
while ((USBReadThread.ThreadState != System.Threading.ThreadState.Stopped) && (USBReadThread.ThreadState != System.Threading.ThreadState.Aborted))
{
Thread.Sleep(10);
}
在USBReadThread这个线程的循环里,会一直这样检测:
if (ThreadStopFlg == true) //判断是否该结束线程了
{
ThreadStopFlg = false;
return;
}
来源:https://www.cnblogs.com/cuihongyu3503319/p/9232275.html
猜你喜欢
- 一、结构型模式结构型模式有什么好处?从程序的结构上实现松耦合,从而可以扩大整体的类结构,用来解决更大的问题二、适配器模式USB网线转换器三、
- 一、场景Android项目的开发过程中,我们项目中的gradle的dependencies闭包中会引入很多三方依赖库,引入的库越多,越容易产
- 前言AOP(Aspect Oriented Programming),即面向切面编程,是Spring框架的大杀器之一。首先,我声明下,我不是
- preHandle: 预先处理,在目标的controller方法执行之前,进行处理postHandle: 在目标的con
- Java压缩文件与解压缩zip文件在日常的使用中经常会使用到像WinRAR或WinZIP这样的压缩文件,通过这些软件可以把一个很大的文件进行
- 这篇文章主要介绍了Java中遍历ConcurrentHashMap的四种方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一
- @ConfigurationProperties实现类型安全的配置问题描述从之前@Value的使用,可以知道@Value可以灵活的把配置文件
- 使用Spring Boot 与Dubbo集成,这里我之前尝试了使用注解的方式,简单的使用注解注册服务其实是没有问题的,但是当你涉及到使用注解
- 什么是冒泡排序冒泡排序指重复地走访过要排序的元素列,依次比较两个相邻的元素,如果顺序(如从小到大)错误就把他们交换过来。走访元素的工作是重复
- 1.问题产生情况我遇到这个问题是做微信开发的时候有些有用的头像用了微信的emoji表情,然而我的mysql数据库用的编码是utf8_gene
- 本Demo使用三个类一个Test类一个自定义的Stack类一个自定义的Queue类可以实现的功能:1.对于一个写在文本文件中的迷宫,能够将其
- 前言在一些开源的框架的源码当中时不时都可以看到volatile这个关键字,最近特意学习一下volatile关键字的使用方法。volatile
- Ribbon是Spring Cloud Netflix全家桶中负责负载均衡的组件,它是一组类库的集合。通过Ribbon,程序员能在不涉及到具
- we can custom min heap or max heap by override the method compare.pack
- 实现原理在之前的文章中,我们介绍了普通的帐号密码登录的方式: SpringBoot + Spring Security 基本使用及个性化登录
- 一、概述无论是什么语言,在多线程编程中,常常会遇到多个线同时操作程某个变量(读/写),如果读/写不同步,则会造成不符合预期的结果。例如:线程
- 在平时的开发中,我们会经常遇到这样一个需求,要在页面通过一个『导出』按钮把查询出的数据导出到 Excel 表格中。本文即为实现上述需求的一个
- 看代码~ //创建socket对象 //第一个参数:设置网
- 这篇文章主要介绍了如何使用java修改文件所有者及其权限,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的
- Unity Shader学习:玻璃材质,供大家参考。主要是通过反射和折射来达到透明的效果,用菲涅尔来混叠。shader部分:Shader &