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

作者:依乐祝

原文地址:https://www.cnblogs.com/yilezhu/p/13168337.html

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

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()

Task.Result跟 Task.GetAwaiter.GetResult()相同吗?怎么选?的更多相关文章

  1. 初步学习async/await,Task.GetAwaiter,Task.Result

    网上关于async/await的知识有很多,看了很多但不如自己实践一遍来得快,所以这里记录下我的理解和大家学习下. 首先以最简单的同步方法来开始如下 private static void Test( ...

  2. .net core Task.Result Wait等造成502

    这两天公众号项目上线,刚开始项目运行没什么问题,但几天之后,访问量激增,服务器崩溃了,每次请求都返回502,一脸懵逼,无从下手,赶紧开日志里的BUG,拿出来一个个改,BUG都改完之后,没有明显的效果, ...

  3. Parallel Programming-Task Result && Continuation Task

    本文主要介绍带有返回值的Task和Continuation Task 带返回值的Task Continuation Task ContinueWhenAll即多任务延续 一.带返回值的Task 1.1 ...

  4. async await task.Result 卡死

    在如下代码中: public async Task<string> GetData() { return await DoWork(); } 在UI线程中调用 var data = Get ...

  5. async,await与task.wait()或task.Result的区别

    你是否曾经与我一样不理解async,await与task.wait()或者task.Result的区别? 接下来,一个Demo让你看出他们之间的区别. static void Main(string[ ...

  6. 一句 Task.Result 就死锁, 这代码还怎么写?

    一:背景 1. 讲故事 前些天把 .NET 高级调试 方面的文章索引到 github 的过程中,发现了一个有意思的评论,详见 文章,截图如下: 大概就是说在 Winform 的主线程下执行 Task. ...

  7. 【C# Task】理解Task中的ConfigureAwait配置同步上下文

    原文:https://devblogs.microsoft.com/dotnet/configureawait-faq/ 作者:Stephen 翻译:xiaoxiaotank 静下心来,你一定会有收获 ...

  8. Task.Run与Task.Factory.StartNew的区别

    Task是可能有延迟的工作单元,目的是生成一个结果值,或产生想要的效果.任务和线程的区别是:任务代表需要执行的作业,而线程代表做这个作业的工作者. 在.Net 4中,Task.Factory.Star ...

  9. Task.Run Vs Task.Factory.StartNew

    在.Net 4中,Task.Factory.StartNew是启动一个新Task的首选方法.它有很多重载方法,使它在具体使用当中可以非常灵活,通过设置可选参数,可以传递任意状态,取消任务继续执行,甚至 ...

随机推荐

  1. [微信营销企划之路]003.Access forbidden!

    引言 继<[微信营销企划之路]001.环境搭建(XAMPP+WeiPHP)>后,有不少朋友反应按照001教程配置虚拟多站点(<VirtualHost/>)后,部分站点会出现Ac ...

  2. [优文翻译]001.真正程序员该是什么样的(How To Be A Real Programmer)

    01.Real Programmers don't write specs -- users should consider themselves lucky to get any programs ...

  3. python基本操作-文件、目录及路径

    目录 1 前言 2 文件夹操作 2.1 查询操作 2.2 创建操作 2.3 删除操作 2.4 修改操作 3 文件操作 3.1 查询操作 3.2 创建操作 3.3 修改操作 3.4 删除 4 路径操作 ...

  4. Netty学习笔记(番外篇) - ChannelHandler、ChannelPipeline和ChannelHandlerContext的联系

    这一篇是 ChannelHandler 和 ChannelPipeline 的番外篇,主要从源码的角度来学习 ChannelHandler.ChannelHandler 和 ChannelPipeli ...

  5. 14 . Python3之MysSQL

    数据库概念 数据库: 按照数据结构来组织.存储.管理数据的仓库` 诞生 计算机的发明是为了做科学计算的,而科学计算需要大量的输入和输出. 早期,可以使用打孔卡片的孔.灯泡的亮灭表示数据输入,输出. 后 ...

  6. DQN(Deep Q-learning)入门教程(六)之DQN Play Flappy-bird ,MountainCar

    在DQN(Deep Q-learning)入门教程(四)之Q-learning Play Flappy Bird中,我们使用q-learning算法去对Flappy Bird进行强化学习,而在这篇博客 ...

  7. Rocket - regmapper - RegMapper

    https://mp.weixin.qq.com/s/aXxgzWwh6unuztjgyVX0iQ 简单介绍RegMapper的实现. 1. 简单介绍 RegMapper使用指定的输入接口,为一组寄存 ...

  8. 【Springboot HBase】遇到的一些问题

    想要运行的代码需要在application中运行 使用@Component并实现CommandLineRunner接口.重写方法@Override run( ) @Component public c ...

  9. 从0开始探究vue-组件化-组件之间传值

    理解 Vue中有个非常重要的核心思想,就是组件化,组件化是为了代码复用 什么是组件化 组件化,就像一个电脑主机里的主板,有内存条的插口,有硬盘,光驱等等的插口,我们的项目,就像一个电脑主机,通过各种组 ...

  10. Java实现 蓝桥杯 算法训练 相邻数对(暴力)

    试题 算法训练 相邻数对 问题描述 给定n个不同的整数,问这些数中有多少对整数,它们的值正好相差1. 输入格式 输入的第一行包含一个整数n,表示给定整数的个数. 第二行包含所给定的n个整数. 输出格式 ...