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

阅读目录

  • 一、什么时候用Thread.Abort();
  • 二、Thread.Abort的用法
  • 三、无法终止线程的情形
  • 四、Catch块中抛出异常
  • 五、Finally块中抛出异常
  • 六、Abort调用的时间

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

回到顶部

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

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

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

回到顶部

二、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

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);

    }

}

主程序

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

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();

    }

}

工具类

1

2

3

4

5

6

7

8

9

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438205.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET MVC 入门7、Hellper与数据的提交与绑定

本系列文章基于ASP.NET MVC Preview5. ASP.NET MVC提供了很多Hellper的方法&#xff0c;Hellper就是一些生成HTML代码的方法&#xff0c;方便我们书写HTML代码(有一部分的朋友更喜欢直接写HTML代码)。我们也可以利用.NET 3.5的扩展方法来书写我们自己的Hellper。 例如&#x…

ASP.NET MVC 入门8、ModelState与数据验证

ViewData有一个ModelState的属性&#xff0c;这是一个类型为ModelStateDictionary的ModelState类型的字典集合。在进行数据验证的时候这个属性是比较有用的。在使用Html.ValidationMessage()的时候&#xff0c;就是从ViewData.ModelState中检测是否有指定的KEY&#xff0c;如果…

ASP.NET MVC 入门9、Action Filter 与 内置的Filter实现(介绍)

本系列文章基于ASP.NET MVC Preview5. 有时候你想在调用action方法之前或者action方法之后处理一些逻辑&#xff0c;为了支持这个&#xff0c;ASP.NET MVC允许你创建action过滤器。Action过滤器是自定义的Attributes&#xff0c;用来标记添加Action方法之前或者Action方法之后…

ASP.NET MVC 入门10、Action Filter 与 内置的Filter实现(实例-防盗链)

本系列文章基于ASP.NET MVC Preview5. 前一篇中我们已经了解了Action Filter 与 内置的Filter实现&#xff0c;现在我们就来写一个实例。就写一个防盗链的Filter吧。 首先继承自FilterAttribute类同时实现IActionFilter接口&#xff0c;代码如下&#xff1a; /// <summary…

base64原理及其编解码的python实现

base64原理及其编解码的python实现base64base64简介base64编码表base64编码原理base64编解码的python实现其他base编码base16base32base36、base58、 base62、 base85、base91、 base92base64 base64简介 base64是一种基于64个可打印字符来表示二进制数据的表示方法。2664&am…

REVERSE-PRACTICE-JarvisOJ-1

REVERSE-PRACTICE-JarvisOJ-1[61dctf]androideasy[61dctf]stheasyDD - Android NormalDD - Android Easy[61dctf]androideasy apk文件&#xff0c;用jadx-gui打开 主要的逻辑为&#xff0c;获取输入&#xff0c;检验输入的长度&#xff0c;输入异或23后与已知数组比较&#xf…

NuGet学习笔记(1) 初识NuGet及快速安装使用

关于NuGet园子里已经有不少介绍及使用经验&#xff0c;本文仅作为自己研究学习NuGet一个记录。 初次认识NuGet是在去年把项目升级为MVC3的时候&#xff0c;当时看到工具菜单多一项Library Package Manager&#xff0c;右键项目文件多了一项Manage Nuget Packages...&#xff0c…

NuGet学习笔记(2) 使用图形化界面打包自己的类库

上文NuGet学习笔记(1) 初识NuGet及快速安装使用说到NuGet相对于我们最重要的功能是能够搭建自己的NuGet服务器&#xff0c;实现公司内部类库的轻松共享更新。在安装好NuGet扩展后&#xff0c;我们已经能够通过NuGet轻松下载自己需要的类库&#xff0c;下面来说一说如何将自己的…

REVERSE-PRACTICE-JarvisOJ-2

REVERSE-PRACTICE-JarvisOJ-2DD - HelloAPK_500DebugMeFindPassDD - Hello macos文件&#xff0c;无壳&#xff0c;ida分析 start函数和sub_100000C90函数没什么作用 主要的逻辑在sub_100000CE0函数&#xff0c;反调试检测和byte_100001040数组的循环变换&#xff0c;最后打印…

NuGet学习笔记(3) 搭建属于自己的NuGet服务器

文章导读 创建NuGetServer Web站点 发布站点到IIS 添加本地站点到包包数据源 在上一篇NuGet学习笔记(2) 使用图形化界面打包自己的类库 中讲解了如何打包自己的类库&#xff0c;接下来进行最重要的一步&#xff0c;从零开始搭建属于自己的NuGet服务器&#xff0c;诚然园子里…

REVERSE-PRACTICE-JarvisOJ-3

REVERSE-PRACTICE-JarvisOJ-3爬楼梯软件密码破解-1Classical CrackMe2Smali爬楼梯 apk文件&#xff0c;放到模拟器里运行一下 “爬一层楼”按钮可按&#xff0c;每按一下&#xff0c;“已爬的楼层”加1层 “爬到了&#xff0c;看FLAG”按钮不可按&#xff0c;应该是“已爬的楼…

管理全局包、缓存和临时文件夹

每当安装、更新或还原包时&#xff0c;NuGet 将管理项目结构多个文件夹之外的包和包信息&#xff1a; name说明和位置&#xff08;每个用户&#xff09;global‑packagesglobal-packages 文件夹是 NuGet 安装任何下载包的位置。 每个包完全展开到匹配包标识符和版本号的子文件…

REVERSE-PRACTICE-JarvisOJ-4

REVERSE-PRACTICE-JarvisOJ-4Classical CrackmeFindKeyClassical Crackme exe程序&#xff0c;输入注册码&#xff0c;输入错误弹窗 查壳发现是.Net程序&#xff0c;dnSpy打开&#xff08;要不要用de4dot unpack无所谓&#xff0c;这里打开的是解包过的程序&#xff09; 按下“…

在解决方案中所使用 NuGet 管理软件包依赖

使用程序包恢复功能可以在提交源代码时, 不需要将 packages 中的程序集文件提交到源代码管理中&#xff0c;大幅减少项目的尺寸。所有NuGet程序包都存储在解决方案的Packages文件夹中。 要启用程序包恢复功能&#xff0c;可右键单击解决方案&#xff08;注意&#xff0c;不是右…

REVERSE-PRACTICE-BUUCTF-1

REVERSE-PRACTICE-BUUCTF-1easyrereverse1reverse2内涵的软件easyre exe程序&#xff0c;无壳&#xff0c;ida分析 左侧函数窗找到main函数&#xff0c;flag提交即可 reverse1 exe程序&#xff0c;运行后提示输入flag&#xff0c;ida分析 左侧函数窗无明显的main函数&#…

REVERSE-PRACTICE-BUUCTF-2

REVERSE-PRACTICE-BUUCTF-2新年快乐[BJDCTF 2nd]guessgamehellowordxor新年快乐 exe程序&#xff0c;运行后提示输入正确的flag&#xff0c;有upx壳&#xff0c;常规工具脱壳即可 ida分析&#xff0c;左侧函数窗找到main函数&#xff0c;F5反汇编&#xff0c;简单的输入比较逻…

REVERSE-PRACTICE-BUUCTF-3

REVERSE-PRACTICE-BUUCTF-3reverse3不一样的flagSimpleRevJava逆向解密reverse3 exe程序&#xff0c;无壳&#xff0c;用ida分析 左侧函数窗最后找到main函数&#xff0c;F5反汇编 先base64&#xff0c;然后顺序加上对应的下标&#xff0c;最后比较&#xff0c;写逆脚本即可得…

console对象的方法log、info、warn、error的区别及几个实用的方法

先说一下console&#xff0c;JavaScript 原生中默认是没有 Console 对象&#xff0c;这是某些浏览器提供的内置对象。 在不同的浏览器里显示可能不同 下面的运行截图中&#xff0c;图中的灰色是运行的这句&#xff0c;灰色下面是此句运行的结果 log()、info()、warn()、error()…

认识ASP.NET 5项目结构和项目文件xproj

ASP.NET 5 在项目结构上做了很大的改变&#xff0c;我们以前熟悉的目录结构与项目文件内容都不太一样了&#xff0c;本篇文章带大家了解 ASP.NET 5 到底跟以前有哪些不一样的地方。 我们先用 Visual Studio 2015 建立一个全新的 ASP.NET 5 网站项目&#xff0c;打开VS2015&…

REVERSE-PRACTICE-BUUCTF-4

REVERSE-PRACTICE-BUUCTF-4刮开有奖[BJDCTF 2nd]8086[GKCTF2020]Check_1n[GXYCTF2019]luck_guy刮开有奖 exe文件&#xff0c;运行后无任何提示&#xff0c;无壳&#xff0c;用ida分析 WinMain->DialogBoxParamA->DialogFunc DialogBoxParamA函数&#xff1a; DialogFun…