dotnet 警惕 Task 的 ContinueWith 带上 OnlyOnFaulted 参数抛出取消异常
本文记录 dotnet 的一个令人迷惑的设计,在 Task 里,有一个叫 ContinueWith 的方法,此方法可以在 Task 完成时执行传入的委托。在 ContinueWith 方法里面,还有一个可选的 TaskContinuationOptions 参数,在此参数里面传入 OnlyOnFaulted 即可在 Task 出错时才执行传入的委托,然而此行为迷惑的是在 Task 正在执行完成却抛出取消异常
在等待任务执行完成之后,干某个活的事情上,有多个可选方法。一个就是老实使用 await 等待 Task 执行完成,然后再继续编写后续逻辑,如以下代码
await task;
干自己的活();
另一个方法就是通过 ContinueWith 方法,比如在使用 Task.Run 执行某个 Foo 方法之后,再 干自己的活 的代码
var task = Task.Run(Foo).ContinueWith(t =>
{
});
以上的 ContinueWith 方法里面传入的委托是不管 Task 的执行状态,无论是成功还是失败都能进入。如果只期望只有在失败时才进入,可以传入 OnlyOnFaulted 参数,代码如下
var task = Task.Run(Foo).ContinueWith(t =>
{
}, TaskContinuationOptions.OnlyOnFaulted);
然而这里存在一个令人迷惑的行为,大家猜猜,当 Foo 正常执行时,等待上面代码的 task 时,是否会抛出异常
答案是抛出 TaskCanceledException 异常
var task = Task.Run(Foo).ContinueWith(t =>
{
}, TaskContinuationOptions.OnlyOnFaulted);
try
{
await task;
}
catch (TaskCanceledException e)
{
}
static void Foo()
{
}
这是因为 dotnet 认为 ContinueWith 里面的委托被取消了
那如果 Task 执行过程中抛出异常呢?看看下面的代码
var task1 = Task.Run(FooWithException).ContinueWith(t =>
{
}, TaskContinuationOptions.OnlyOnFaulted);
await task1;
static void FooWithException()
{
throw new Exception("lindexi is doubi");
}
可以看到 task1 正常被等待,啥事都没有发生
这么特别诡异起来了,很好就在代码里面挖坑。毕竟写了以上代码的开发者更多的是进行测试 Task 异常的情况。再加上如果偶尔的正常执行完成,抛出的是取消异常,很多开发者都会以为是正常被取消而已
也有伙伴说,那分开两个 Task 等待好了,如以下代码
var task = Task.Run(Foo);
var task1 = task.ContinueWith(t =>
{
}, TaskContinuationOptions.OnlyOnFaulted);
但是以上代码解决不了的问题是,如果期望等待整个大的 Task 执行完成,也就是 Task 和 ContinueWith 里面的内容全部执行完成,那这个逻辑就诡异了
也就是只有在无需等待 ContinueWith 执行结果的情况下,才可以推荐使用 OnlyOnFaulted 参数。没有等待 ContinueWith 执行结果,且刚好 Task 是正常执行的,这是不会将取消异常抛到 UnobservedTaskException 里的
TaskScheduler.UnobservedTaskException += (sender, eventArgs) =>
{
};
在 dotnet 的设计里面,如果一个 Task 存在异常,且这个 Task 的异常没有被任何代码捕获到,将在此 Task 被 GC 时,抛到 UnobservedTaskException 里面。可以通过如上代码的事件,获取到是否存在有 Task 的异常没有被捕获。进入 UnobservedTaskException 事件的异常不会导致应用挂掉,只是用来记录日志或者埋点上报等,让开发者知道有某个 Task 的异常没有被捕获
可以通过如下方式获取本文的源代码,先创建一个空文件夹,接着使用命令行 cd 命令进入此空文件夹,在命令行里面输入以下代码,即可获取到本文的代码
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin f758059f3f9f9bbfe2e7205a137d2e5b3da31f7a
以上使用的是 gitee 的源,如果 gitee 不能访问,请替换为 github 的源。请在命令行继续输入以下代码
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
git pull origin f758059f3f9f9bbfe2e7205a137d2e5b3da31f7a
获取代码之后,进入 HojohoyahobaWayfahurhalqeje 文件夹
更多博客,请参阅我的 博客导航
dotnet 警惕 Task 的 ContinueWith 带上 OnlyOnFaulted 参数抛出取消异常的更多相关文章
- js进阶解决浏览器缓存不能自动更新的问题(在ajax的url上带上一个参数,可以是日期,或者是随机数)(随机数Math.random)(取得日期的毫秒数:new Date().getTime();)
js进阶解决浏览器缓存不能自动更新的问题(在ajax的url上带上一个参数,可以是日期,或者是随机数)(随机数Math.random)(取得日期的毫秒数:new Date().getTime();) ...
- 在XP系统中自带的 msvcrt.dll 和 Vista 中的 msvcrt.dll 版本不同,导致抛出的异常不同
然而,在XP系统中,系统自带的 msvcrt.dll 和 Vista 中的 msvcrt.dll 版本不同, 并没有这个 _except_handler4_common ,结果就出现了启动程序时,遇到 ...
- 记一次asp.net core 在iis上运行抛出502.5错误
asp.net core 在iis上运行抛出502.5异常的部分原因以及解决方案 环境说明 已安装 .net core runtime 2.1.401 已安装 .net core windows ho ...
- 调用远程主机上的 RMI 服务时抛出 java.rmi.ConnectException: Connection refused to host: 127.0.0.1 异常原因及解决方案
最近使用 jmx 遇到一个问题,client/server 同在一台机器上,jmx client能够成功连接 server,如果把 server 移植到另一台机器上192.168.134.128,抛出 ...
- 案例复现,带你分析Priority Blocking Queue比较器异常导致的NPE问题
摘要:本文通过完整的案例复现来演示在什么情况会触发该问题,同时给出了处理建议.希望读者在编程时加以借鉴,避免再次遇到此类问题. 本文分享自华为云社区<Priority Blocking Queu ...
- Asp.net Core dotnet 发布类库文件 带上注释,发布预发行版,带上所有引用
带上注释 效果图 带上所有引用 效果图 预发行版 效果图 由于微软取消了 project.json 这个json 转而用了csproj 用于保存配置 所以懵逼很大一会 资料来源 project.j ...
- 【HDU 4940】Destroy Transportation system(无源无汇带上下界可行流)
Description Tom is a commander, his task is destroying his enemy’s transportation system. Let’s repr ...
- .NetCore HttpClient发送请求的时候为什么自动带上了一个RequestId头部?
奇怪的问题 最近在公司有个系统需要调用第三方的一个webservice.本来调用一个下很简单的事情,使用HttpClient构造一个SOAP请求发送出去拿到XML解析就是了. 可奇怪的是我们的请求在运 ...
- 记得ajax中要带上AntiForgeryToken防止CSRF攻击
经常看到在项目中ajax post数据到服务器不加防伪标记,造成CSRF攻击 在Asp.net Mvc里加入防伪标记很简单在表单中加入Html.AntiForgeryToken()即可. Html.A ...
- ZOJ 2314 带上下界的可行流
对于无源汇问题,方法有两种. 1 从边的角度来处理. 新建超级源汇, 对于每一条有下界的边,x->y, 建立有向边 超级源->y ,容量为x->y下界,建立有向边 x-> 超级 ...
随机推荐
- 探讨三维模型OBJ格式轻量化在三维展示效果上的重要性
探讨三维模型OBJ格式轻量化在三维展示效果上的重要性 三维模型的OBJ格式轻量化在三维展示效果方面具有重要性.以下是对三维模型OBJ格式轻量化在三维展示效果上的重要性进行分析: 1.提高渲染性能:原始 ...
- 自己动手做一个批量doc转换为docx文件的小工具
前言 最近遇到了一个需求,就是要把大量的doc格式文件转换为docx文件,因此就动手做了一个批量转换的小工具. 背景 doc文件是什么? "doc" 文件是一种常见的文件格式,通常 ...
- 探秘Kubernetes:在本地环境中玩转容器技术
在云计算时代,Kubernetes 已成为云原生技术的真正基石.它是应用程序容器的编排动力源,可跨多个集群自动部署.扩展和运行容器.Kubernetes 不仅仅是一个流行词,它还是一种模式转变,是现代 ...
- CC2530 中的ZigBee协议栈
CC2530 中的ZigBee协议栈 1.何为协议栈 ZigBee协议栈将各个层的协议集合在一起,并以函数的形式实现,并且向用户提供接口,用户能够直接调用. 它本身就为一个工程. 2. 如何使用 开始 ...
- 卷积神经网络学习笔记——ZFNet(Tensorflow实现)
完整代码及其数据,请移步小编的GitHub地址 传送门:请点击我 如果点击有误:https://github.com/LeBron-Jian/DeepLearningNote 这个网络应该是CNN的鼻 ...
- 分析即服务(AaaS)是什么?终于有人讲清楚了
随着世界数据领域的地位和规模的不断扩大,大数据.人工智能和云计算正在结合起来,以分析即服务的形式为企业提供急需的喘息机会 . 让我们简要回顾一下 2010 年以来发生的事情. 这十年来我们见证了许多技 ...
- spark dstaframe 多字段统计
val aggCols = List("Pclass","Age","Fare") .map(colName=>functions.a ...
- k8s 深入篇———— docker 镜像是什么[二]
前言 简单介绍一下docker的镜像. 正文 前面讲到了容器的工作原理了(namespace 限制了时间, cgroup限制了资源),知道docker 历史的也知道,docker 之所以能够称为容器大 ...
- mysql 重新整理——索引优化explain简单介绍 [八]
前言 做开发的我们晓得一个道理,就是说不是说你说这东西性能稳定就是性能稳定,你说发版本就发版本,这个是测试部门说了算的. 那么索引优化的关键也就是说一个我们来逐步调优,调优就要知道我们这条语句在mys ...
- vue-manage-system 版本更新,让开发更加简单
vue-manage-system 近期进行了一次版本升级,主要是支持了更多功能.升级依赖版本和优化样式,并且上线了官方文档网站,大部分功能都有文档或者使用示例,更加适合新手上手开发,只需要根据实际业 ...