Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 11946|回复: 0

多线程(7)多线程中的异常处理

[复制链接]
  • TA的每日心情
    奋斗
    2024-11-24 15:47
  • 签到天数: 804 天

    [LV.10]以坛为家III

    2053

    主题

    2111

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    726782
    发表于 2021-4-11 13:55:31 | 显示全部楼层 |阅读模式

      多线程使用过程中,除了线程同步的问题要考虑外,异常处理也是经常要面对的事情。

    默认主线程捕获不到异步线程的异常

    如下代码:

     1 namespace ConsoleApplication29
     2 {
     3     class Program
     4     {
     5         static void Main(string[] args)
     6         {
     7             //异步线程的异常处理
     8             try
     9             {
    10                 Task.Factory.StartNew(() => 
    11                 {
    12                     throw new Exception("异步线和发生异常了!");
    13                 });
    14             }
    15             catch (Exception ex)
    16             {
    17                 //这里是捕获不到的
    18                 Console.WriteLine(ex.ToString());
    19             }
    20 
    21             Console.ReadKey();
    22         }
    23     }
    24 }
    View Code

    常用的异常处理方法

    1,在异步线程内部使用try/catch

    如下代码:

     1 namespace ConsoleApplication29
     2 {
     3     class Program
     4     {
     5         static void Main(string[] args)
     6         {
     7             //异步线程的异常处理
     8             //1,在异步线程内部使用try/catch
     9             Task.Factory.StartNew(() =>
    10             {
    11                 try
    12                 {
    13                     throw new Exception("异步线和发生异常了!");
    14                 }
    15                 catch (Exception ex)
    16                 {
    17                     Console.WriteLine(ex.ToString());
    18                 }
    19             });
    20 
    21             Console.ReadKey();
    22         }
    23     }
    24 }
    View Code

     运行结果:

    2,调用Task的Wait方法

     如下代码:

    注意:

    除了调用Task的Wait方法后,在主线程可以捕获异常外,对于有返回值的Task,只要接收了它的返回值就不再需要调用Wait方法了。

     1 namespace ConsoleApplication29
     2 {
     3     class Program
     4     {
     5         static void Main(string[] args)
     6         {
     7             //异步线程的异常处理
     8             //2,调用Task的Wait方法
     9             try
    10             {
    11                 var task = Task.Factory.StartNew(() =>
    12                 {
    13                     throw new Exception("异步线和发生异常了!");
    14                 });
    15                 task.Wait();
    16             }
    17             catch (Exception ex)
    18             {
    19                 Console.WriteLine(ex.ToString());
    20             }
    21 
    22             Console.ReadKey();
    23         }
    24     }
    25 }
    View Code

     

    运行结果:

    3,在Task的ContinueWith方法中读取Task的Exception属性

    如下代码:

     1 namespace ConsoleApplication29
     2 {
     3     class Program
     4     {
     5         static void Main(string[] args)
     6         {
     7             //异步线程的异常处理
     8             //3,在Task的ContinueWith方法中读取Task的Exception属性
     9             Task.Factory.StartNew(() =>
    10             {
    11                 throw new Exception("异步线和发生异常了!");
    12             }).ContinueWith(t => 
    13             {
    14                 if (t.IsFaulted)
    15                 {
    16                     Console.WriteLine(t.Exception.InnerException);
    17                 }
    18             }, TaskContinuationOptions.OnlyOnFaulted);
    19 
    20             Console.ReadKey();
    21         }
    22     }
    23 }
    View Code

     

    运行结果:

     4,全局设置TaskScheduler.UnobservedTaskException

     如果异步线程里的异常没有被处理,也没有调用Task.Wait方法将异常传给主线程处理,最严重的后果可能会导致整个应用程序奔溃。详细原因参考:System.Threading.Tasks.Task引起的IIS应用程序池崩溃

    所以,为了保证应用程序不会因为异步线程的异常未被处理导致挂掉,推荐的做法是,全局设置TaskScheduler.UnobservedTaskException。

    如果是web程序,可以在Global的Application_Start事件中进行设置,如下代码:

    1 protected override void Application_Start(object sender, EventArgs e)
    2 {
    3     System.Threading.Tasks.TaskScheduler.UnobservedTaskException += (s, v) =>
    4     {
    5         v.SetObserved();
    6     };
    7 }
    View Code

     

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-12-23 00:14 , Processed in 0.145588 second(s), 30 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表