大家都知道在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方法后,怎样保证线程停止后代码才会继续执行

  1. var thread = new Thread(
  2. new ThreadStart(
  3. () =>
  4. {
  5. while (true)
  6. {
  7. //该线程会进行无限循环,自己不会结束
  8. Thread.Sleep(100);
  9. }
  10. }));
  11. thread.IsBackground = true;
  12. thread.Start();//启动线程
  13. thread.Abort();//调用Thread.Abort方法试图强制终止thread线程
  14. //上面调用Thread.Abort方法后线程thread不一定马上就被终止了,所以我们在这里写了个循环来做检查,看线程thread是否已经真正停止。其实也可以在这里使用Thread.Join方法来等待线程thread终止,Thread.Join方法做的事情和我们在这里写的循环效果是一样的,都是阻塞主线程直到thread线程终止为止
  15. while (thread.ThreadState!=ThreadState.Aborted)
  16. {
  17. //当调用Abort方法后,如果thread线程的状态不为Aborted,主线程就一直在这里做循环,直到thread线程的状态变为Aborted为止
  18. Thread.Sleep(100);
  19. }
  20. //当跳出上面的循环后就表示我们启动的线程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,然后就等待这个线程顺利结束:

  1. USBOP.ThreadStopFlg = true;
  2. while ((USBReadThread.ThreadState != System.Threading.ThreadState.Stopped) && (USBReadThread.ThreadState != System.Threading.ThreadState.Aborted))
  3. {
  4. Thread.Sleep(10);
  5. }
USBOP.ThreadStopFlg = true;
while ((USBReadThread.ThreadState != System.Threading.ThreadState.Stopped) && (USBReadThread.ThreadState != System.Threading.ThreadState.Aborted))
{
Thread.Sleep(10);
}

在USBReadThread这个线程的循环里,会一直这样检测:

    1. if (ThreadStopFlg == true) //判断是否该结束线程了
    2. {
    3. ThreadStopFlg = false;
    4. return;
    5. }

最新文章

  1. WAP端 穿透问题和解决方法
  2. 关于GC的几篇文章
  3. 跨域资源共享 CORS
  4. Android项目实战(七):Dialog主题Activity实现自定义对话框效果
  5. 采集网页数据---Using Java
  6. orcad中的PSpice仿真加入厂商模型
  7. iOS_SN_Socket网络编程(一)
  8. RabbitMQ 使用demo
  9. #WEB安全基础 : HTML/CSS | 0x11 浅谈GET和POST
  10. git操作github仓库基本操作
  11. jquery easyui datagrid 将值作为img显示图片时报404 undefined
  12. linux笔记_day03
  13. Jetson tk1 hash sum mismatch
  14. java中BufferedImage类的用法
  15. CocoaPods出错
  16. 10、Dockerfile实战-PHP
  17. 【原创】有关Silverlight中 "Silverlight提示4004错误" 的解决方案及思路。
  18. 解题:USACO15JAN Grass Cownoisseur
  19. vertex shader(2)
  20. Kprobe

热门文章

  1. python 读空的json文件
  2. 插入10W数据的两个程序比较
  3. 查看nginx版本和安装的模块
  4. Builder(建造者)
  5. oracle RAC的客户端HA配置
  6. 【源码学习之spark core 1.6.1 standalone模式下的作业提交】
  7. Mysql语句转义
  8. [sql]java.sql.Types的具体对应值(jdbcType)
  9. JavaScript--语法4--函数1
  10. 微软Azure DevOps自动化部署