服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C#如何优雅的结束线程

C#如何优雅的结束线程

2022-11-17 13:49宏宇 C#

这篇文章主要介绍了C#如何优雅的结束一个线程,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

大家都知道在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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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,然后就等待这个线程顺利结束:

?
1
2
3
4
5
6
7
8
9
10
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这个线程的循环里,会一直这样检测:

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

到此这篇关于C#如何优雅的结束一个线程的文章就介绍到这了,更多相关C#结束线程内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://www.cnblogs.com/cuihongyu3503319/p/9232275.html

延伸 · 阅读

精彩推荐
  • C#C#实现无限级联下拉列表框

    C#实现无限级联下拉列表框

    这篇文章主要为大家详细介绍了C#实现无限级联下拉列表框的相关资料,感兴趣的小伙伴们可以参考一下...

    C#教程网9162021-11-15
  • C#C# 实现Trim方法去除字符串前后的所有空格

    C# 实现Trim方法去除字符串前后的所有空格

    这篇文章主要介绍了C# 实现Trim方法去除字符串前后的所有空格,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    IT技术小趣屋4422022-10-20
  • C#C#中事件的定义和使用

    C#中事件的定义和使用

    在使用事件时,通常要定义两个方法,一个是和事件定义的委托签名一致的方法。下面让我们看看使用事件的具体步骤。...

    张逸8322021-11-24
  • C#OpenCvSharp实现Mat对象简单的像素操作

    OpenCvSharp实现Mat对象简单的像素操作

    这篇文章主要介绍了OpenCvSharp实现Mat对象简单的像素操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋...

    haixin-5618842022-10-17
  • C#C#时间操作类分享

    C#时间操作类分享

    这篇文章主要为大家分享了C#时间操作类,秒转换成分钟,获得两个日期的间隔等,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    孤者自清6672022-01-11
  • C#利用C#代码实现图片旋转360度

    利用C#代码实现图片旋转360度

    本文介绍利用C#代码实现图片旋转360度,具体实例代码已附上,仅供大家参考,希望对大家有所帮助...

    逆心8462021-12-10
  • C#C#中Entity Framework常见报错汇总

    C#中Entity Framework常见报错汇总

    给大家总结了C#中Entity Framework常见报错,以及处理这些错误的方法,希望能够为你提供到帮助。...

    C#教程网8372022-02-13
  • C#C# winform自定义翻页控件详解

    C# winform自定义翻页控件详解

    这篇文章主要为大家详细介绍了C# winform自定义翻页控件的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    安东家的安东4932022-01-21