如何更好地理解“异步-处理多个异常”中的代码/语句;篇文章

本文关键字:异常 代码 文章 语句 处理 更好 何更好 异步 | 更新日期: 2023-09-27 18:13:58

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

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 **

不过,上面的代码是从"Async -处理多个异常"博客文章中复制的第一个片段,它告诉我们:

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

问题在哪里:

    这篇文章是错的?
    哪些代码/语句以及如何更改才能正确理解它?
  1. 我在复制文章的第一个代码片段时犯了错误?
  2. 这是由于一个错误在。net 4.0/VS2010异步CTP扩展,我使用?

Update1(在响应svick的回答)

添加代码

//******  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所说:

被捕获的AggregateException只包含一个抛出的异常(NullReferenceExceptionArgumentException取决于子进程的执行顺序任务)

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

Update2(在响应svick的回答)

执行svick的代码:

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 ?

如何更好地理解“异步-处理多个异常”中的代码/语句;篇文章

文章有误。在运行代码时,awaitTask包含一个异常,看起来像这样:

AggregateException
  AggregateException
    NullReferenceException
  AggregateException
    ArgumentException

await(或者更具体地说,TaskAwaiter.GetResult())在这里所做的是获取外部的AggregateException并重新抛出它的第一个子异常。这里,这是另一个AggregateException,这就是抛出的内容。

Task有多个异常,其中一个在await之后被直接重新抛出的代码示例是使用Task.WhenAll()而不是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);
}

回应你的"Update 2",推理仍然和svick的答案一样。该任务包含一个AggregateException,但等待它抛出第一个InnerException

您需要的其他信息在任务中。WhenAll documentation(强调我的):

如果任何提供的任务在故障状态下完成,则返回的任务也将在故障状态下完成,其中其异常将包含来自每个提供的任务的未包装异常集的聚合。

使Task的异常看起来像:

AggregateException 
    NullReferenceException 
    ArgumentException