专栏首页依乐祝Task.Result跟 Task.GetAwaiter.GetResult()相同吗?怎么选?

Task.Result跟 Task.GetAwaiter.GetResult()相同吗?怎么选?

前几天在用线程池执行一些任务时运到一种情形,就是回调方法中使用到了异步方法,但是回调方法貌似不支持async await的写法。这时候我应该如何处理呢?是使用Task.Result来获取返回结果,还是使用GetAwaiter.GetResult()呢?本文就来探讨下吧。

这里先上我这种场景的伪代码:

ThreadPool.QueueUserWorkItem(ExcuteScanProcess, node);

ExcuteScanProcess这个回调方法中

private void ExcuteScanProcess(object state)
{
    ……其他处理……
    repository.UpdateAsync(node).ConfigureAwait(false).GetAwaiter().GetResult();
    ……其他处理……
}

如上图所示repository.UpdateAsync(node)属于一部方法,这时候我想要等待它异步执行完成之后再执行后续的逻辑。这时候我有两种选择,是直接

repository.UpdateAsync(node).ConfigureAwait(false).GetAwaiter().GetResult();

好呢,还是

repository.UpdateAsync(node).ConfigureAwait(false).Result;

好呢?

为此我查找了相关的资料,对它俩的区别做一个简单的总结:

其实这两个使用方式是差不多的。不过,还是有一点小小的区别的:如果任务失败,Task.GetAwaiter().GetResult()会直接抛出异常,而Task.Result则会把异常包装在AggregateException中。从这个角度说Task.GetAwaiter().GetResult()要优于Task.Result。毕竟它少了异常的包装操作,即直接抛出异常,而不是把异常包装在AggregateException中。

下面的引言解释了为什么Task.Result不仅仅包含Task.GetAwaiter().GetResult()(由于“非常高的兼容性”)的异常传播行为。

如前所述,我们有一个非常高的兼容性标准,因此我们避免了改动。因此,Task.Wait保留了始终包装的原始行为。但是,您可能会发现自己处在某些高级情况下,这些情况下您想要的行为类似于所采用的同步阻塞Task.Wait,但是您希望将原始异常展开而不是传播,而不是将其封装在AggregateException中。为此,您可以直接定位任务的等待者。当您编写“ await task;”时,编译器Task.GetAwaiter()会将其转换为方法的用法,这将返回具有GetResult()方法的实例。当用于有故障的任务时,GetResult()将传播原始异常(这是“ await task;” 如何获得其行为)。因此,您可以使用“task.GetAwaiter().GetResult()如果您想直接调用此传播逻辑。

https://blogs.msdn.microsoft.com/pfxteam/2011/09/28/task-exception-handling-in-net-4-5/

GetResult”实际上表示“检查任务是否有错误” 通常,我会尽力避免对异步任务进行同步阻塞。但是,在少数情况下,我确实违反了该准则。在那些罕见的情况下,我的首选方法是GetAwaiter().GetResult()因为它保留任务异常,而不是将它们包装在中AggregateException

总结

通过上述内容的阐述,因此在那些必须对异步任务进行同步阻塞的场景中,我选择使用GetAwaiter().GetResult()

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • C# 多线程(18):一篇文章就理解async和await

    扯淡了 17 篇,这篇终于开始学习 async 和 await 了,有了前面的基础,来理解 async 和 await 就容易理解多了。

    痴者工良
  • 聊聊多线程那一些事儿(task)之 一聊聊多线程那一些事儿(task)之 三 异步取消和异步方法聊聊多线程那一些事儿 之 四 经典应用(取与舍、动态创建)

      多线程,一个多么熟悉的词汇,作为一名程序员,我相信无论是从事什么开发语言,都能够轻轻松松说出几种实现多线程的方式,并且在实际工作种也一定用到过多线程,比如:...

    小小许
  • C# 使用相同权限调用 cmd 传入命令

    如果想要用相同的权限运行一个程序,可以使用 ProcessStartInfo 的方法

    林德熙
  • 10个小技巧助您写出高性能的ASP.NET Core代码

    今天这篇文章我们来聊一聊如何提升并优化ASP.NET Core应用程序的性能,本文的大部分内容来自翻译,当然中间穿插着自己的理解,希望对大家有所帮助!话不多说开...

    依乐祝
  • .Net异步编程知多少

    1. 引言 最近在学习Abp框架,发现Abp框架的很多Api都提供了同步异步两种写法。异步编程说起来,大家可能都会说异步编程性能好。但好在哪里,引入了什么问题,...

    圣杰
  • C#多线程(13):任务基础①

    .NET 中,有三种异步编程模式,分别是基于任务的异步模式(TAP)、基于事件的异步模式(EAP)、异步编程模式(APM)。

    痴者工良
  • 将 async/await 异步代码转换为安全的不会死锁的同步代码

    发布于 2018-03-16 03:58 更新于 2018-08...

    walterlv
  • 这会是你见过讲得最清楚的【异步爬虫指南】

    在执行一些 IO 密集型任务的时候,程序常常会因为等待 IO 而阻塞。比如在网络爬虫中,如果我们使用 requests 库来进行请求的话,如果网站响应速度过慢,...

    一墨编程学习
  • 使用 Task.Wait()?立刻死锁(deadlock)

    发布于 2017-10-27 15:54 更新于 2018-04...

    walterlv

作者介绍

依乐祝

安徽容知日新科技股份有限公司高级软件开发工程师

安徽容知日新科技股份有限公司 · 高级软件开发工程师 (已认证)

专栏

精选专题

活动推荐

扫码关注云+社区

领取腾讯云代金券