首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在任务内部抛出异常- "await“vs Wait()

在任务内部抛出异常- "await“vs Wait()
EN

Stack Overflow用户
提问于 2011-09-08 04:44:08
回答 3查看 27.5K关注 0票数 22
static async void Main(string[] args)
{
    Task t = new Task(() => { throw new Exception(); });

    try
    {                
        t.Start();
        t.Wait();                
    }
    catch (AggregateException e)
    {
        // When waiting on the task, an AggregateException is thrown.
    }

    try
    {                
        t.Start();
        await t;
    }
    catch (Exception e)
    {
        // When awating on the task, the exception itself is thrown.  
        // in this case a regular Exception.
    }           
}

在第三方公共语言中,当在任务内部抛出异常时,它用AggregateException包装。

但在使用await关键字时,不会发生同样的情况。

对这种行为的解释是什么?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2011-09-08 17:41:41

我们的目标是让它看起来/行为像同步版本。Jon Skeet在他的Eduasync系列文章中做了很好的解释,特别是这篇文章:

http://codeblog.jonskeet.uk/2011/06/22/eduasync-part-11-more-sophisticated-but-lossy-exception-handling/

票数 10
EN

Stack Overflow用户

发布于 2017-03-23 18:28:00

在第三方物流中使用AggregateException是因为您可以让多个任务处于等待操作中(任务可以附加子任务),因此它们中的许多任务都会抛出异常。在此处查看子任务部分中的异常:

https://msdn.microsoft.com/ru-ru/library/dd997417(v=vs.110).aspx

await中,你总是只有一个任务。

另请参阅https://msdn.microsoft.com/ru-ru/library/dd997415(v=vs.110).aspx

票数 3
EN

Stack Overflow用户

发布于 2019-07-31 23:10:03

下面是Stephen Toub的详细解释,为什么Task.Wait()和await在异常类型上存在差异:

Task Exception Handling in .NET 4.5

在.NET 4中设计Task.Wait时,我们选择了总是传播聚合。这一决定不仅受到不重写细节的需要的影响,而且还受到当时任务的主要用例的影响,即fork/join并行性,其中潜在的多个异常相当常见。

虽然在高层次上类似于Task.Wait (即直到任务完成才会取得前进的进展),但“等待任务”代表了一组非常不同的主要场景。“等待任务”最常见的用法不是用于fork/join并行性,而是将一个连续的、同步的代码片段转换为一个连续的、异步的代码片段。在代码中执行同步操作的地方,您可以将其替换为由任务表示的异步操作并“等待”它。因此,虽然你当然可以使用await for fork/join操作(例如,利用Task.WhenAll),但它不是80%的情况。此外,Watson 4.5引入了System.Runtime.ExceptionServices.ExceptionDispatchInfo,,它解决了允许您在不丢失堆栈跟踪和.NET存储桶等异常细节的情况下跨线程编组异常的问题。给定一个异常对象,将其传递给ExceptionDispatchInfo.Create,它将返回一个ExceptionDispatchInfo对象,其中包含对该异常对象的引用及其详细信息的副本。当抛出异常时,ExceptionDispatchInfo的抛出方法用于恢复异常的内容,并在不丢失原始信息的情况下抛出该异常(当前调用堆栈信息将附加到已存储在异常中的信息中)。

考虑到这一点,再一次选择总是抛出第一个或总是抛出一个聚合,对于“等待”,我们选择总是抛出第一个。然而,这并不意味着您不能访问相同的详细信息。在所有情况下,任务的Exception属性仍然返回一个包含所有异常的AggregateException,因此您可以捕获抛出的任何异常,并在需要时返回咨询Task.Exception。是的,当在“task.Wait()”和“await task”之间切换时,这会导致异常行为之间的差异,但我们认为这是两个坏处中较小的一个。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/7340309

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档