Task Parallel Library (TPL) 中,当你使用async/await 语法关键字时,你可能遇到以下异常处理的情况: Catch 块只会处理第一个异常而忽略其它的异常。来看下面代码块:

   1:          private static async void TestCatchExceptionWithTPL()
   2:          {
   3:              try
   4:              {
   5:                  await Task.Factory.StartNew(() =>
   6:                     {
   7:                         Task.Factory.StartNew(() =>
   8:                            { throw new NullReferenceException(); },
   9:                                 TaskCreationOptions.AttachedToParent);
  10:                         Task.Factory.StartNew(() =>
  11:                            { throw new ArgumentException(); },
  12:                                   TaskCreationOptions.AttachedToParent);
  13:                     });
  14:              }
  15:              catch (AggregateException aex)
  16:              {
  17:                  // this catch will never be target
  18:              }
  19:              catch (Exception ex)
  20:              {
  21:                  Console.WriteLine("## {0} ##", ex.GetType().Name);
  22:              }
  23:          }

执行上面的代码,有注意8,11行分别有两个Exception,而这时到第一个Catch块中AggregateException只会捕捉第一个NullReferenceException异常,这是By Design的问题。有个解决方案是这样的:

   1:              try
   2:              {
   3:                  Task t = Task.Factory.StartNew(() =>
   4:                      {
   5:                          Task.Factory.StartNew(() =>
   6:                            { throw new NullReferenceException(); },
   7:                                  TaskCreationOptions.AttachedToParent);
   8:                          Task.Factory.StartNew(() =>
   9:                            { throw new ArgumentException(); },
  10:                                 TaskCreationOptions.AttachedToParent);
  11:                      });
  12:                  await t.ContinueWith(tsk => { if (tsk.Exception != null) throw tsk.Exception; });
  13:              }
  14:              catch (AggregateException ex)
  15:              {
  16:                  foreach (var exc in ex.Flatten().InnerExceptions)
  17:                  {
  18:                      Console.WriteLine(exc.GetType().Name);
  19:                  }
  20:              }

注意上面12行代码,使用了CoutinueWith方法,为了让代码更加简洁了,我们可以写一个扩展方法:

        /// <summary>
        /// ThrowMultiple
        /// </summary>
        /// <param name="t">Task</param>
        /// <returns>Task type</returns>
        public static Task ThrowMultiple(this Task t)
        {
            return t.ContinueWith(tsk => { if (tsk.Exception != null) throw tsk.Exception; });
        }
 
        /// <summary>
        /// ThrowMultiple
        /// </summary>
        /// <typeparam name="T">Task this</typeparam>
        /// <param name="t">Task t</param>
        /// <returns>Task generic</returns>
        public static Task<T> ThrowMultiple<T>(this Task<T> t)
        {
            return t.ContinueWith(tsk =>
           {
               if (tsk.Exception != null)
                   throw tsk.Exception;
               return tsk.Result;
           });
        }

然后代码就是变成这样了:

   1:              try
   2:              {
   3:                  await Task.Factory.StartNew(() =>
   4:                     {
   5:                         Task.Factory.StartNew(() =>
   6:                            { throw new NullReferenceException(); },
   7:                                 TaskCreationOptions.AttachedToParent);
   8:                         Task.Factory.StartNew(() =>
   9:                            { throw new ArgumentException(); },
  10:                                   TaskCreationOptions.AttachedToParent);
  11:                     }).ThrowMultiple();
  12:              }
  13:              catch (AggregateException aex)
  14:              {
  15:                  // this catch will never be target
  16:              }
  17:              catch (Exception ex)
  18:              {
  19:                  Console.WriteLine("## {0} ##", ex.GetType().Name);
  20:              }

有看到上面代码11行的变化为我们扩展方法。就这么简单,以上代码在Vs2012下 .net framework 4.5 version 下测试通过,希望对你开发有帮助。

您可能感兴趣的文章:

Asp.net MVC 4 异步方法

作者:Petter Liu
出处:http://www.cnblogs.com/wintersun/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。
该文章也同时发布在我的独立博客中-Petter Liu Blog。

Async下处理多个异常相关推荐

  1. (笔记)Linux Root下的.gvfs出现异常解决办法

    (笔记)Linux Root下的.gvfs出现异常解决办法 参考文章: (1)(笔记)Linux Root下的.gvfs出现异常解决办法 (2)https://www.cnblogs.com/tdyi ...

  2. Linux中的报错命令,Linux学习教程-Linux下命令的一些异常情况

    导读 命令不全:在命令没有输入完 (引号或括号没有配对),就不小心按下了Enter键,终端会提示出一个>代表命令不完整,这是可以继续输入,也可以ctrl+c终止输入,重新再来.(下面sed命令使 ...

  3. win10下桌面图标显示异常

    如何win10下桌面图标显示异常 原因: 图标缓存损坏 解决方案 删除损坏图标 重新创建 重启电脑 如果还是加载不出 原因:损坏图标缓存已安装进win10 进入window instllar 在重新删 ...

  4. Win7下PDF图标显示异常排除

    Win7下PDF图标显示异常排除 文件图标显示异常的原因及检查排除步骤 文件关联异常 图标缓存异常 图标文件损坏 文件图标显示异常的原因及检查排除步骤 文件关联异常 Control Panel\All ...

  5. C#下没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG))

    C#下没有注册类 (异常来自 HRESULT:0x80040154 (REGDB_E_CLASSNOTREG)) 参考文章: (1)C#下没有注册类 (异常来自 HRESULT:0x80040154 ...

  6. linux下怎么查看程序异常,linux程序莫名异常怎么查

    内存异常经常导致程序出现莫名其妙的错误,往往很难查证,本文介绍在linux下的各种常见内存异常的查证工具和方法. 1 访问空指针/未初始化指针/重复释放内存 对于像访问空指针.未初始化指针(非法地址) ...

  7. oracle11g exp 00028,解决Linux系统下exp导入EXP-00028异常

    问题描述: 在Linux系统中,对某个数据库用户进行exp导出备份时,出现下述异常: Oracle Database 11g Enterprise Edition Release 11.2.0.4.0 ...

  8. Linux下使用Vim编辑器异常退出E325:ATTENTION错误

    Linux下使用vim编辑文件时,因为闪退或者卡住异常关闭终端导致出现E325:ATTENTION错误如下所示: 在当前目录下使用ls命令查看,此时并没有.main.cpp.swp文件 必须使用ls ...

  9. window40系统怎么重装不下服务器,Win10系统异常不想重装怎么办 四种系统修复方法哪种比较好...

    Win10系统使用久了,垃圾多了使系统不堪重负,碰上有些恶意软件会修改设置导致系统异常,或者不小心操作修改一些服务都能使系统受伤.当你的系统操作反应越来越慢,或者已经到了瘫痪地步,该如何办?重装?太麻 ...

最新文章

  1. Spring boot ----RestTemplate学习笔记
  2. BSP 二叉树再次讨论
  3. JS getAttribute和setAttribute(取得和设置属性)的使用介绍
  4. 全面解析并实现逻辑回归(Python)
  5. linux防火墙配置连接atlas,ATLAS在ubuntu下的安装使用
  6. mysql导入查询失败_mysql数据库中的查询失败
  7. html箭头实现流程箭头,js实现带箭头的进度流程
  8. L2TP详解(五)——Client Initiated隧道和会话建立过程
  9. 今日头条的针锋相对让腾讯开始焦虑,天天快报能否占据一席之位?
  10. bat批处理命令:实现读取文件内容,并调用浏览器打开网址,搜索文件内容
  11. linux比较两个文件的不同
  12. git .git目录提交_入侵git目录
  13. 新品上市|A股场内衍生品大盘点
  14. 购买一台计算机需要哪些配件,组装一台电脑需要哪些配件【详细列举】
  15. 在VB中如何使IE窗口最大化
  16. 防止软件进行微信小程序自动刷票、免费投票刷票器手机版的安全设计
  17. python中的pip命令在cmd下用不了?
  18. 自回归AR模型、移动平均MA模型与自回归移动平均ARMA模型的比较分析
  19. Ubuntu16.04配置pytorch环境(CPU版)
  20. vue子路由跳转问题

热门文章

  1. php insert Oracle clob 字段处理问题
  2. 实验分享:用Python生成个性化二维码
  3. 第8章 SQL语言(一)
  4. zookeeper的设计猜想-Follower角色
  5. synchronized的基本认识
  6. Spring5的集成兼容
  7. 微信支付 - 构建商户订单
  8. SpringIOC容器介绍
  9. 权限操作-springSecurity概述及快速入门步骤分析
  10. 数据库-优化-数据库系统配置优化-操作系统优化