我最近正在阅读一些使用大量异步方法的代码,但有时需要同步执行它们。该代码的作用是:
Foo foo = GetFooAsync(...).GetAwaiter().GetResult();
这是否与
Foo foo = GetFooAsync(...).Result;
Task.GetAwaiter().GetResult()
优先于Task.Wait
and Task.Result
因为它传播异常而不是将它们包装在AggregateException
。然而,这三种方法都可能导致死锁和线程池饥饿问题。应该避免它们async/await
.
下面的引用解释了原因Task.Wait
and Task.Result
不简单地包含异常传播行为Task.GetAwaiter().GetResult()
(由于“兼容性非常高”)。
正如我之前提到的,我们有非常高的兼容性标准,因此我们避免了重大更改。像这样,Task.Wait
保留其始终包裹的原始行为。但是,您可能会发现自己处于某些高级情况下,您需要类似于使用的同步阻塞的行为Task.Wait
,但是您希望原始异常以未包装的形式传播,而不是将其封装在AggregateException
。为此,您可以直接定位任务的等待者。当你写“await task;
”,编译器将其转换为使用Task.GetAwaiter()
方法,它返回一个实例,该实例具有GetResult()
方法。当用于有故障的任务时,GetResult()
将传播原始异常(这就是“await task;
”得到它的行为)。因此,您可以使用“task.GetAwaiter().GetResult()
”如果你想直接调用这个传播逻辑。
https://devblogs.microsoft.com/pfxteam/task-exception-handling-in-net-4-5/ https://devblogs.microsoft.com/pfxteam/task-exception-handling-in-net-4-5/
“GetResult
”实际上意味着“检查任务是否有错误”
一般来说,我会尽力避免同步阻塞异步任务。然而,在少数情况下我确实违反了该准则。在那些罕见的情况下,我首选的方法是GetAwaiter().GetResult()
因为它保留了任务异常而不是将它们包装在AggregateException
.
https://blog.stephencleary.com/2014/12/a-tour-of-task-part-6-results.html https://blog.stephencleary.com/2014/12/a-tour-of-task-part-6-results.html
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)