zoukankan      html  css  js  c++  java
  • C#多线程之旅(7)——终止线程

    先交代下背景,写《C#多线程之旅》这个系列文章主要是因为以下几个原因:1.多线程在C/S和B/S架构中用得是非常多的;2.而且多线程的使用是非常复杂的,如果没有用好,容易造成很多问题。

     

    原文地址:C#多线程之旅(7)——终止线程 (原创:博客园-Jackson0714)

    C#多线程之旅目录:

    C#多线程之旅(1)——介绍和基本概念

    C#多线程之旅(2)——创建和开始线程

    C#多线程之旅(3)——线程池

    C#多线程之旅(4)——APM初探

    C#多线程之旅(5)——同步机制介绍

    C#多线程之旅(6)——详解多线程中的锁

     C#多线程之旅(7)——终止线程

    更多文章正在更新中,敬请期待......

    一、什么时候用Thread.Abort();

    当我们想要立即终止一个线程时,可以用调用Thread.Abort方法来终止线程。这个和协作式取消不一样。

    终止当前线程时会在当前线程上引发ThreadAbortException 异常。ThreadAbortExcetion是一个可以被应用程序捕获的特殊异常,在catch 块中会自动重新抛出这个异常,除非在catch块中调用ResetAbort方法。ResetAbort方法可以取消掉终止的请求,而且可以防止catch中再次抛出的ThreadAbortException终止当前线程。未执行的Finally块会在线程终止前执行。

    二、Thread.Abort的用法

    例子:

     

    名称

    代码

    计算限制的

    操作

    public class ThreadWork
    {
        public static void DoWork()
        {
            try
            {
                for (int i = 0; i < 100; i++)
                {
                    Tool.WriteMessage("Thread - working.", ConsoleColor.Green, ConsoleColor.White);
                    Thread.Sleep(1000);
                }
            }
            catch (ThreadAbortException e)
            {
                Tool.WriteMessage("Thread - Caught ThreadAbortException - resetting.", ConsoleColor.Green, ConsoleColor.White);
                Tool.WriteMessage("Thread - Exception message: " + e.Message, ConsoleColor.Red, ConsoleColor.White);
                
                /*--如果调用Thread.ResetAbort()-----
                1.取消终止线程的请求,并恢复线程,继续执行ResetAbort后面的语句,然后执行catch块之后的语句
                2.若Catch块之后有Finally块,则执行Finally块,然后执行Finally块后面的语句。
                */
                /*----如果没有调用Thread.ResetAbort()----
                1.finally块在线程终止前执行,finally块之后的语句不会被执行,然后线程终止。
                */
                //Thread.ResetAbort();
                //Tool.WriteMessage("Thread - ResetAbort", ConsoleColor.Green, ConsoleColor.White);
            }
            finally
            {
                Tool.WriteMessage("Thread - Finally blocks were executed.", ConsoleColor.Green, ConsoleColor.White);
            }
            Tool.WriteMessage("Thread - still alive and working.", ConsoleColor.Green, ConsoleColor.White);
            Thread.Sleep(1000);
            Tool.WriteMessage("Thread - finished working.", ConsoleColor.Green, ConsoleColor.White);
        }
    }

    主程序

    public class ThreadAbortTest
    {
        public static void Main()
        {
            try
            {
                ThreadStart myThreadDelegate = new ThreadStart(ThreadWork.DoWork);
                Thread myThread = new Thread(myThreadDelegate);
                myThread.Start();//启动线程myThread,执行DoWork方法
                Thread.Sleep(100);
                Tool.WriteMessage("Main - aborting my thread.", ConsoleColor.Blue, ConsoleColor.White);
                myThread.Abort();//终止线程myThread
                myThread.Join();//等待线程myThread结束
                Tool.WriteMessage("Main - ending.", ConsoleColor.White, ConsoleColor.White);
            }
            catch(Exception ex)
            {
                throw ex;
            }
            Console.ReadKey();
        }
    }

    工具类

    public static class Tool
    {
        public static void WriteMessage(string message, ConsoleColor writeColor ,ConsoleColor backColor)
        {
            Console.ForegroundColor = writeColor;
            Console.WriteLine(message);
            Console.ForegroundColor = backColor;
        }
    }

     

    (1)调用Thread.Abort()的输出结果:

     

    (2)未调用Thread.Abort()输出结果:

     

    (3)流程:

    (1)当主线程调用myThread.Abort()后,线程myThread抛出异常,线程myThread捕获到异常

    (2)在myThread catch块中

    如果调用Thread.ResetAbort()-----

         Step1.取消终止线程的请求,并恢复线程,继续执行ResetAbort后面的语句,然后执行catch块之后的语句

         Step2.若catch块之后有Finally块,则执行执行Finally块,然后执行Finally块后面的语句。

     如果没有调用Thread.ResetAbort()----

          1.finally块在线程终止前执行,finally块之后的语句不会被执行,然后线程终止。

     

    三、无法终止线程的情形

    当调用线程的Abort方法时,不能保证线程立即终止,有可能永远不能终止。这种情形发生在catch或finally块中存在长时间或无限的耗时操作时。

    只有当catch或finally块中代码执行完才能终止线程。所以我们可以调用线程的Join方法来等待线程的完成或终止。

    四、Catch块中抛出异常

    应用程序将会被终止,Finally块不会被执行

     

    五、Finally块中抛出异常

    应用程序将会被终止

     

    六、Abort调用的时间

    (1)线程Start之前调用Abort

    线程会在Start被调用时终止线程。

    (2)线程Sleeping的时候调用Abort

    线程被中断,然后终止线程

    (3)线程Blocked的时候调用Abort

    线程被中断,然后终止线程

    (4)线程被挂起的时候调用Abort

    Throw ThreadStartException 引发Abort的调用,然后AbortRequested 被加到正在被终止的线程的ThreadState属性

    (5)一个托管线程正在执行非托管代码时调用Abort

    ThreadAbortException不会被抛出直到线程返回托管代码。

    (6)如果同时Abort两个线程,有可能一个线程会设置状态信息,而另外一个线程执行Abort的方法。然而,应用程序不会检测到这种情形。


    作  者: Jackson0714
    出  处:http://www.cnblogs.com/jackson0714/
    关于作者:专注于微软平台的项目开发。如有问题或建议,请多多赐教!
    版权声明:本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。
    特此声明:所有评论和私信都会在第一时间回复。也欢迎园子的大大们指正错误,共同进步。或者直接私信
    声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是作者坚持原创和持续写作的最大动力!

  • 相关阅读:
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (四) 自动化部署
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (三) 服务观测
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (二) 部署微服务程序
    阿里云 k8s 部署 Spring Cloud Alibaba 微服务实践 (一) 部署 Nacos
    C++知识点
    libmkl 学习笔记
    基于tesseract-OCR进行中文识别
    poco编译与运行
    Linux下的I/O复用与epoll详解(转载)
    高并发网络编程之epoll详解(转载)
  • 原文地址:https://www.cnblogs.com/jackson0714/p/AbortThread.html
Copyright © 2011-2022 走看看