• Async下处理多个异常


         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

  • 相关阅读:
    php中向mysql插入数据
    W3Cschool菜鸟教程离线版下载链接
    Call to undefined function mysqli_connect()
    Windows下MySQL 5.6安装及配置详细图解
    请不要再责怪你的程序员“太慢”
    工欲善其事必先利其器
    PHP正则表达式
    matlab画柱状图
    matlab 把数组中的NaN去除掉
    建模2017A题 角度lingo代码
  • 原文地址:https://www.cnblogs.com/wintersun/p/2878569.html
Copyright © 2020-2023  润新知