注意!你的Thread.Abort方法真的让线程中止了吗?

你们都知道在C#里面,咱们可使用 Thread.Start方法来启动一个线程,当咱们想中止执行的线程时可使用Thread.Abort方法来强制中止正在执行的线程,可是请注意,你肯定调用了Thread.Abort方法后线程就马上中止了吗? 答案是:不是!安全

 

下面咱们来解释一下Abort方法是如何工做的。由于公用语言运行时管理了全部的托管的线程,一样它能在每一个线程内抛出异常。Abort方法能在目标线程中抛出一个ThreadAbortException异常从而致使目标线程的终止。不过Abort方法被调用后,目标线程可能并非立刻就终止了。由于只要目标线程正在调用非托管的代码并且尚未返回的话,该线程就不会当即终止而若是目标线程在调用非托管的代码并且陷入了一个死循环的话,该目标线程就根本不会终止。不过这种状况只是一些特例,更多的状况是目标线程在调用托管的代码,一旦Abort被调用那么该线程就当即终止了。spa

 

其实一个线程在运行时,咱们能够经过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方法后,怎样保证线程中止后代码才会继续执行code

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方法是经过在线程上抛异常来终止线程的,这样可能会产生一些意想不到的问题。最好的办法是在启动的线程中加信号灯,当想要终止线程执行时就更改信号灯的状态,启动的线程当读到信号灯状态改变后本身结束代码的执行,这才是最安全的作法。blog

相关文章
相关标签/搜索