如何更好地理解来自“异步处理多个异常”的代码/语句文章? [英] How to better understand the code/statements from "Async - Handling multiple Exceptions" article?

查看:316
本文介绍了如何更好地理解来自“异步处理多个异常”的代码/语句文章?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

运行以下C#控制台应用程序

Running the following C# console app

class Program
{  static void Main(string[] args)
   {  Tst();
      Console.ReadLine();
   }
   async static Task  Tst()
   {
       try
       {
           await Task.Factory.StartNew
             (() =>
                {
                   Task.Factory.StartNew
                       (() =>
                         { throw new NullReferenceException(); }
                         , TaskCreationOptions.AttachedToParent
                        );
               Task.Factory.StartNew
                       (  () =>
                               { throw new ArgumentException(); }
                               ,TaskCreationOptions.AttachedToParent
                       );
                }
             );
    }
    catch (AggregateException ex)
    {
        // this catch will never be target
        Console.WriteLine("** {0} **", ex.GetType().Name);

//******  Update1 - Start of Added code
        foreach (var exc in ex.Flatten().InnerExceptions)
        {
             Console.WriteLine(exc.GetType().Name);
        }
//******  Update1 - End of Added code
    }
    catch (Exception ex)
    {
       Console.WriteLine("## {0} ##", ex.GetType().Name);
    }
 }

产生输出:

** AggregateException **

但是,上面的代码是从异步处理多个异常博客文章,它告诉它:

Though, the code above is reproducing the first snippet from "Async - Handling multiple Exceptions" blog article, which tells about it :


以下代码将捕获单个NullReferenceException或
ArgumentException异常(AggregateException将被忽略)

the following code will catch a single NullReferenceException or ArgumentException exception (the AggregateException will be ignored)

问题在哪里? / p>

Where is the problem:


  1. 文章错了?

    哪些代码/语句和如何更改才能正确理解?

  2. 我在复制文章的第一个代码段时发生错误?

  3. 这是由于.NET 4.0 / VS2010中的错误Async CTP扩展,我在使用?



Update1(响应 svick的答案



添加代码后

Update1 (in response to svick's answer)

Upon adding the code

//******  Update1 - Start of Added code
        foreach (var exc in ex.Flatten().InnerExceptions)
        {
             Console.WriteLine(exc.GetType().Name);
        }
//******  Update1 - End of Added code

生成的输出是:

** AggregateException **
NullReferenceException

所以,同样评论Matt Smith


<被捕获的code> AggregateException 只包含抛出的
异常之一($ code> NullReferenceException 或
ArgumentException 取决于孩子的执行顺序
任务)

the AggregateException that is caught, contains only one of the exceptions that was thrown (either the NullReferenceException or the ArgumentException depending on the order of execution of the child Tasks)

最有可能的是,文章仍然是正确的,或者至少非常有用。我只需要了解如何更好地阅读/理解/使用它

Most probably, the article is still correct or, at least, very useful. I just need to understand how to better read/understand/use it

执行svick的代码:

Executing svick's code:

internal class Program
{
  private static void Main(string[] args)
  {
    Tst();
    Console.ReadLine();
  }

  private static async Task Tst()
  {
    try
    {
      await TaskEx.WhenAll
        (
          Task.Factory.StartNew
            (() =>
               { throw new NullReferenceException(); }
            //, TaskCreationOptions.AttachedToParent
            ),
          Task.Factory.StartNew
            (() =>
               { throw new ArgumentException(); }
            //,TaskCreationOptions.AttachedToParent
            )

        );
    }
    catch (AggregateException ex)
    {
      // this catch will never be target
      Console.WriteLine("** {0} **", ex.GetType().Name);

      //******  Update1 - Start of Added code
      foreach (var exc in ex.Flatten().InnerExceptions)
      {
        Console.WriteLine("==="+exc.GetType().Name);
      }
      //******  Update1 - End of Added code
    }
    catch (Exception ex)
    {
      Console.WriteLine("## {0} ##", ex.GetType().Name);
    }
  }
}

产生:

## NullReferenceException ##

输出。

为什么不会生成或捕获 AggregateException

Why isn't AggregateException produced or caught?

推荐答案

文章错误。当您运行代码时,等待 ed 任务包含一个如下所示的异常:

The article is wrong. When you run your code, the awaited Task contains an exception that looks something like this:

AggregateException
  AggregateException
    NullReferenceException
  AggregateException
    ArgumentException

什么等待(或更具体地说, TaskAwaiter.GetResult() )这里是否需要外部 AggregateException 并重新抛出其第一个小孩异常。在这里,这是另一个 AggregateException ,所以这是抛出的。

What await (or, more specifically, TaskAwaiter.GetResult()) does here is that it takes the outer AggregateException and rethrows its first child exception. Here, that's another AggregateException, so that's what is thrown.

代码示例,其中一个任务有多个异常,其中一个异常是直接重新抛出,在 await 将使用 Task.WhenAll() / code>而不是 AttachedToParent

Example of code where a Task has multiple exceptions and one of them is directly rethrown after await would be to use Task.WhenAll() instead of AttachedToParent:

try
{
    await Task.WhenAll(
        Task.Factory.StartNew(() => { throw new NullReferenceException(); }),
        Task.Factory.StartNew(() => { throw new ArgumentException(); }));
}
catch (AggregateException ex)
{
    // this catch will never be target
    Console.WriteLine("** {0} **", ex.GetType().Name);
}
catch (Exception ex)
{
    Console.WriteLine("## {0} ##", ex.GetType().Name);
}

这篇关于如何更好地理解来自“异步处理多个异常”的代码/语句文章?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆