gpt4 book ai didi

c# - 为什么总是传播来自子任务的许多异常中的一个?

转载 作者:行者123 更新时间:2023-12-02 22:03:00 25 4
gpt4 key购买 nike

我正在努力更好地掌握 TPL 中异常和错误处理的基本原理(并且在 .NET 4.5 async/await 任务中运气更好)

对我之前的问题稍作修改 "How to better understand the code/statements from "Async - Handling multiple Exceptions" article?" C# 控制台应用程序代码运行 2 个 分离的内部嵌套 附加(依赖)子项(更新:抱歉,开始一个问题但以另一个问题结束!)任务:

class Program
{
static void Main(string[] args)
{ Tst();
Console.ReadLine();
}
async static Task Tst()
{
try
{
await Task.Factory.StartNew
(() =>
{
Task.Factory.StartNew
( () => {
Console.WriteLine("From 1st child");
throw new NullReferenceException();
}
, TaskCreationOptions.AttachedToParent
);
Task.Factory.StartNew
( () =>
{
Console.WriteLine("From 2nd child");
throw new ArgumentException();
}
,TaskCreationOptions.AttachedToParent
);
}
);
}
catch (AggregateException ex)
{
Console.WriteLine("** {0} **", ex.GetType().Name);
foreach (var exc in ex.Flatten().InnerExceptions)
{
Console.WriteLine(exc.GetType().Name);
}
}
catch (Exception ex)
{
Console.WriteLine("## {0} ##", ex.GetType().Name);
}
}

产生交替(非确定性)的输出:

From 1st child
From 2nd child
** AggregateException **
ArgumentException

From 1t child
From 2nd child
** AggregateException **
NullReferenceException

似乎总是传播/捕获子任务之一的唯一一个异常。

为什么只有一个异常被传播/捕获?
我会更好地理解是否始终捕获子任务的所有异常,或者更确切地说,所有异常都被捕获

在这种情况下,是否有可能同时捕获或不捕获异常?

最佳答案

您不应将父/子任务与 async 混合使用。它们并非旨在一起使用。

作为 his (correct) answer to your other question 的一部分,svick 已经回答了这个问题.您可以这样想:

  • 每个内部 StartNew 都得到一个异常,它被包装到一个 AggregateException 中并放在返回的 Task 上。
  • 外部 StartNew 从其子任务中获取两个 AggregateException,并将其包装到返回的 Task< 中的另一个 AggregateException/
  • 当您await Task 时,将引发第一个内部异常。忽略任何其他内容。

您可以通过保存 Task 并在 await 引发异常后检查它们来观察此行为:

async static Task Test()
{
Task containingTask, nullRefTask, argTask;
try
{
containingTask = Task.Factory.StartNew(() =>
{
nullRefTask = Task.Factory.StartNew(() =>
{
throw new NullReferenceException();
}, TaskCreationOptions.AttachedToParent);
argTask = Task.Factory.StartNew(() =>
{
throw new ArgumentException();
}, TaskCreationOptions.AttachedToParent);
});
await containingTask;
}
catch (AggregateException ex)
{
Console.WriteLine("** {0} **", ex.GetType().Name);
}
}

如果在 WriteLine 上放置一个断点,您可以看到来自两个子任务的异常都被放置在父任务上。 await 运算符只传播其中一个,所以这就是为什么你只捕获一个。

关于c# - 为什么总是传播来自子任务的许多异常中的一个?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16580125/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com