第六节:深入研究Task实例方法ContinueWith的参数TaskContinuationOptions
一. 整体说明
揭秘:
该章节的性质和上一个章节类似,也是一个扩展的章节,主要来研究Task类下的实例方法ContinueWith中的参数TaskContinuationOptions。
通过F12查看TaskContinuationOptions的源码,知道主要有这么几个参数:
①. LazyCancellation:在延续取消的情况下,防止延续的完成直到完成先前的任务。
(下面的例子task2取消,原先的延续关系不复存在,task1和task3可以并行执行)
②. ExecuteSynchronously:希望执行前面那个task的thread也在执行本延续任务
(下面的例子执行task2的Thread和执行task1的Thread是同一个,所有二者的线程id相同)
③. NotOnRanToCompletion和OnlyOnRanToCompletion
NotOnRanToCompletion:延续任务必须在前面task非完成状态才能执行
OnlyOnRanToCompletion:延续任务必须在前面task完成状态才能执行
(下面例子:注释掉异常的这句代码task2不能执行,task3能执行;不注释,task2能执行,task3不能执行)
源码如下:
[Serializable]
[Flags]
public enum TaskContinuationOptions
{
// 摘要:
// Default = "Continue on any, no task options, run asynchronously" 指定应使用默认行为。
// 默认情况下,完成前面的任务之后将安排运行延续任务,而不考虑前面任务的最终 System.Threading.Tasks.TaskStatus。
None = ,
//
// 摘要:
// 提示 System.Threading.Tasks.TaskScheduler 以一种尽可能公平的方式安排任务,这意味着较早安排的任务将更可能较早运行,而较晚安排运行的任务将更可能较晚运行。
PreferFairness = ,
//
// 摘要:
// 指定某个任务将是运行时间长、粗粒度的操作。 它会向 System.Threading.Tasks.TaskScheduler 提示,过度订阅可能是合理的。
LongRunning = ,
//
// 摘要:
// 指定将任务附加到任务层次结构中的某个父级。
AttachedToParent = ,
//
// 摘要:
// 如果尝试附有子任务到创建的任务,指定 System.InvalidOperationException 将被引发。
DenyChildAttach = ,
//
// 摘要:
// 防止环境计划程序被视为已创建任务的当前计划程序。 这意味着像 StartNew 或 ContinueWith 创建任务的执行操作将被视为 System.Threading.Tasks.TaskScheduler.Default
// 当前计划程序。
HideScheduler = ,
//
// 摘要:
// 在延续取消的情况下,防止延续的完成直到完成先前的任务。
LazyCancellation = ,
//
// 摘要:
// 指定不应在延续任务前面的任务已完成运行的情况下安排延续任务。 此选项对多任务延续无效。
NotOnRanToCompletion = ,
//
// 摘要:
// 指定不应在延续任务前面的任务引发了未处理异常的情况下安排延续任务。 此选项对多任务延续无效。
NotOnFaulted = ,
//
// 摘要:
// 指定只应在延续任务前面的任务已取消的情况下才安排延续任务。 此选项对多任务延续无效。
OnlyOnCanceled = ,
//
// 摘要:
// 指定不应在延续任务前面的任务已取消的情况下安排延续任务。 此选项对多任务延续无效。
NotOnCanceled = ,
//
// 摘要:
// 指定只应在延续任务前面的任务引发了未处理异常的情况下才安排延续任务。 此选项对多任务延续无效。
OnlyOnFaulted = ,
//
// 摘要:
// 指定只应在延续任务前面的任务已完成运行的情况下才安排延续任务。 此选项对多任务延续无效。
OnlyOnRanToCompletion = ,
//
// 摘要:
// 指定应同步执行延续任务。 指定此选项后,延续任务将在导致前面的任务转换为其最终状态的相同线程上运行。 如果在创建延续任务时已经完成前面的任务,则延续任务将在创建此延续任务的线程上运行。
// 只应同步执行运行时间非常短的延续任务。
ExecuteSynchronously = ,
}
二. 实际测试
下面通过代码来说明默认情况下、LazyCancellation、ExecuteSynchronously、NotOnRanToCompletion和OnlyOnRanToCompletion的作用和效果。
1. 默认情况
默认情况下,task1执行完后→task2→task2执行完后→task3。
{
Task task1 = new Task(() =>
{
Thread.Sleep();
Console.WriteLine("task1 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
});
var task2 = task1.ContinueWith(t =>
{
Console.WriteLine("task2 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
});
var task3 = task2.ContinueWith(t =>
{
Console.WriteLine("task3 tid={0}, dt={1} {2}", Thread.CurrentThread.ManagedThreadId, DateTime.Now, task2.Status);
});
task1.Start();
}
运行结果: task1执行完后→ task2执行→task2执行完后→ task3执行。

2. LazyCancellation
作用:取消该线程,该线程的前一个线程和后一个线程并行执行。
{
CancellationTokenSource source = new CancellationTokenSource();
source.Cancel();
Task task1 = new Task(() =>
{
Thread.Sleep();
Console.WriteLine("task1 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
});
var task2 = task1.ContinueWith(t =>
{
Console.WriteLine("task2 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
}, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Current);
var task3 = task2.ContinueWith(t =>
{
Console.WriteLine("task3 tid={0}, dt={1} {2}", Thread.CurrentThread.ManagedThreadId, DateTime.Now, task2.Status);
});
task1.Start();
}
运行结果: task2线程已经被取消,task1线程和task2线程并行执行。

3. ExecuteSynchronously
作用:希望执行前面那个task的thread也在执行本延续任务。
{
Task task1 = new Task(() =>
{
Thread.Sleep();
Console.WriteLine("task1 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
});
var task2 = task1.ContinueWith(t =>
{
Console.WriteLine("task2 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
}, TaskContinuationOptions.ExecuteSynchronously);
task1.Start();
}
结果:task1和task2线程的线程id相同。

4. NotOnRanToCompletion和OnlyOnRanToCompletion
NotOnRanToCompletion:延续任务必须在前面task非完成状态才能执行。
OnlyOnRanToCompletion:延续任务必须在前面task完成状态才能执行。
{
Task task1 = new Task(() =>
{
Thread.Sleep();
Console.WriteLine("task1 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
//手动制造异常,表示不能执行完毕
//(注释掉这句话task2不能执行,task3能执行)
//不注释,task2能执行,task3不能执行
//throw new Exception("hello world");
});
var task2 = task1.ContinueWith(t =>
{
Console.WriteLine("task2 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
}, TaskContinuationOptions.NotOnRanToCompletion);
var task3 = task1.ContinueWith(t =>
{
Console.WriteLine("task3 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
}, TaskContinuationOptions.OnlyOnRanToCompletion);
task1.Start();
}
分析:task2和task3均为task的延续线程,当task1报错时候,task2执行,task3不能执行;当task1正常时候,task2不能执行,task3能执行。
task1报错时的运行结果:

task2正常时的运行结果:


第六节:深入研究Task实例方法ContinueWith的参数TaskContinuationOptions的更多相关文章
- VUE2.0实现购物车和地址选配功能学习第六节
第六节 地址列表过滤和展开所有的地址 html:<li v-for="(item,index) in filterAddress">js: new Vue({ el:' ...
- 第四百一十六节,Tensorflow简介与安装
第四百一十六节,Tensorflow简介与安装 TensorFlow是什么 Tensorflow是一个Google开发的第二代机器学习系统,克服了第一代系统DistBelief仅能开发神经网络算法.难 ...
- 第九节: 利用RemoteScheduler实现Sheduler的远程控制 第八节: Quartz.Net五大构件之SimpleThreadPool及其四种配置方案 第六节: 六类Calander处理六种不同的时间场景 第五节: Quartz.Net五大构件之Trigger的四大触发类 第三节: Quartz.Net五大构件之Scheduler(创建、封装、基本方法等)和Job(创建、关联
第九节: 利用RemoteScheduler实现Sheduler的远程控制 一. RemoteScheduler远程控制 1. 背景: 在A服务器上部署了一个Scheduler,我们想在B服务器上 ...
- CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第六节
原文链接 第六节:全局内存和CUDA RPOFILER Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在 ...
- 风炫安全web安全学习第三十六节课-15种上传漏洞讲解(一)
风炫安全web安全学习第三十六节课 15种上传漏洞讲解(一) 文件上传漏洞 0x01 漏洞描述和原理 文件上传漏洞可以说是日常渗透测试用得最多的一个漏洞,因为用它获得服务器权限最快最直接.但是想真正把 ...
- 基于Extjs的web表单设计器 第六节——界面框架设计
基于Extjs的web表单设计器 基于Extjs的web表单设计器 第一节 基于Extjs的web表单设计器 第二节——表单控件设计 基于Extjs的web表单设计器 第三节——控件拖放 基于Extj ...
- 第一百二十六节,JavaScript,XPath操作xml节点
第一百二十六节,JavaScript,XPath操作xml节点 学习要点: 1.IE中的XPath 2.W3C中的XPath 3.XPath跨浏览器兼容 XPath是一种节点查找手段,对比之前使用标准 ...
- delphi 线程教学第六节:TList与泛型
第六节: TList 与泛型 TList 是一个重要的容器,用途广泛,配合泛型,更是如虎添翼. 我们先来改进一下带泛型的 TList 基类,以便以后使用. 本例源码下载(delphi XE8版本) ...
- 第十六节、基于ORB的特征检测和特征匹配
之前我们已经介绍了SIFT算法,以及SURF算法,但是由于计算速度较慢的原因.人们提出了使用ORB来替代SIFT和SURF.与前两者相比,ORB有更快的速度.ORB在2011年才首次发布.在前面小节中 ...
随机推荐
- python_库学习_02_微信自动回复机器人
一.python发展的趋势日益庞大,微信也有对应的库itchat.这次的实例做做成可在任意电脑运行的微信自动回复机器人exe.文件. 二.完成这个小应用我们需要装一些库,, itchat:这个东东不出 ...
- python3 shell 中添加清屏
在windows中: 安装目录 \Lib( D:\Python37\Lib) 中添加 ClearWindow.py 文件,文件内容: """ Clear Window ...
- [经验总结] 从其它sheet页引用数据生成图表时没有图例的解决办法
1.先给出一个在有数据区域的sheet页中生成的图表,比较全,图表和图例全部都有,如下图: 2.但是如果在其它 sheet页中引用该有数据的sheet数据时并生成图表,生成的图表只有图表区域显示,图例 ...
- Python爬虫【实战篇】bilibili视频弹幕提取
两个重要点 1.获取弹幕的url是以 .xml 结尾 2.弹幕url的所需参数在视频url响应的 javascript 中 先看代码 import requests from lxml import ...
- 先vue-cli,再nuxt试试路由
https://segmentfault.com/a/1190000007933349
- C# for循环或者foreach往List中添加对象的时候前面的数据总被最后加入的覆盖
昨天我旁边小姐姐遇到一个问题,就是在执行for循环往list添加数据的时候,前面的数据信息总是被后面的数据信息所覆盖. 这样编写就会造成这样的数据效果:(所有的数据都会被覆盖) 问题原因:对 ...
- day16-面向对象基础(三)
今日摘要 今天主要整理一下这俩天学习的内容,面向对象也快学完了,深刻的认识到面向对象就是一个思想,怎么把思想理解了,其他也就不是什么事了 1.类的约束 2.类的类方法与静态方法 3.类的反射 4.类的 ...
- 初识服务发现及Consul框架的简单使用
初识服务发现及Consul框架的简单使用 1.什么是服务发现? 服务发现组件记录了(大规模)分布式系统中所有服务的信息,人们或者其它服务可以据此找到这些服务. DNS 就是一个简单的例子. 当然, ...
- SpringBoot开发案例之整合Activiti工作流引擎
前言 JBPM是目前市场上主流开源工作引擎之一,在创建者Tom Baeyens离开JBoss后,JBPM的下一个版本jBPM5完全放弃了jBPM4的基础代码,基于Drools Flow重头来过,目前官 ...
- You earned your Program Management Professional (PgMP)® Credential
You earned your Program Management Professional (PgMP)® Credential. pasting