Task.Result与.GetAwaiter.GetResult()相同吗?
我最近正在阅读一些使用大量asynchronous方法的代码,但有时候需要同步执行它们。 代码确实:
Foo foo = GetFooAsync(...).GetAwaiter().GetResult();
这是一样的
Foo foo = GetFooAsync(...).Result;
?
很多。 一个小的区别:如果Task
失败, GetResult()
将直接引发exception,而Task.Result
将抛出一个AggregateException
。 然而,当它是async
的时候,使用其中的哪一个有什么意义? 100倍更好的select是使用await
。
另外,你不打算使用GetResult()
。 这意味着仅供编译器使用,而不是为了您。 但是,如果你不想讨厌的AggregateException
,使用它。
https://github.com/aspnet/Security/issues/59
“最后一句话:你应该尽量避免使用
Task.Result
和Task.Wait
,因为它们总是把内部exception封装在一个AggregateException
并用一个通用的(发生一个或多个错误)replace消息,这使得debugging更加困难即使不应该经常使用同步版本,也应该考虑使用Task.GetAwaiter().GetResult()
来代替。
http://blog.stephencleary.com/2014/12/a-tour-of-task-part-6-results.html
“
GetResult
”实际上是指“检查任务是否有错误”一般来说,我尽我所能避免同步阻塞asynchronous任务。 但是,有一些情况我违反了这个准则。 在这些罕见的情况下,我首选的方法是
GetAwaiter().GetResult()
因为它保留了任务exception,而不是将它们包装在一个AggregateException
。
http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/task-exception-handling-in-net-4-5.aspx
正如我前面提到的,我们有一个非常高的兼容性,因此我们避免了变化。 因此,
Task.Wait
保留了始终包装的原始行为。 但是,您可能会发现自己处于某些高级情况,您希望类似于Task.Wait
使用的同步阻塞的Task.Wait
,但是希望将原始exception传播到未包装的位置,而不是将其封装在AggregateException
。 为了达到这个目的,你可以直接定位任务的服务器。 当你写“await task;
“,编译器将其翻译成Task.GetAwaiter()
方法的用法,该方法返回一个具有GetResult()
方法的实例。 当在一个有故障的Task上使用时,GetResult()
会传播原来的exception(这是“await task;
”的方式)。 如果你想直接调用这个传播逻辑,你可以使用“task.GetAwaiter().GetResult()
”。
另一个区别是, async
函数只返回Task
而不是Task<T>
那么你不能使用
GetFooAsync(...).Result;
而
GetFooAsync(...).GetAwaiter().GetResult();
仍然有效。
我知道问题中的示例代码是针对案例Task<T>
,但是一般会问到这个问题。