第六节:深入研究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年才首次发布.在前面小节中 ...
随机推荐
- Ajax 与文件上传
一 Ajax篇 1 ajax简介(Asynchronous Javascript And XML) 异步,Js,XML,即使用Javascript语言与服务器进行异步交互,传输的数据为xml(可扩展标 ...
- EXTJS的使用
最近一段时间一直使用Extjs作为前端,通过HTTP与.net后端进行交互,今天总结一下EXTJS,方便以后复习. 1.概念: ExtJS可以用来开发RIA也即富客户端的AJAX应用,是一个用java ...
- webApi 验证basic-authentication认证的资源的各种语言的实现
HTTP Basic authentication (BA) 是一个基于http请求的,简单验证.详细资料:https://en.wikipedia.org/wiki/Basic_access_aut ...
- 基于开发者中心DevOps流水线快速上云
导读:“DevOps”这个词现在很流行,它具体指的是什么呢?本文介绍了DevOps和开发者中心DevOps流水线,图文并茂,解答您的疑惑. 那么DevOps是什么?开发者中心<DevOps流水线 ...
- VUE 绑定背景图片的写法
<div v-bind:style='{"background-image":"url("+imgUrl+")"}' >< ...
- Flutter之List
void listDemo() { // 1.list的创建 listCreate(); // 2.多种类型的输出 listPrint(); // 3.添加数据 listAddElement(); / ...
- Shell命令-系统信息及显示之dmesg、uptime
文件及内容处理 - dmesg.uptime 1. dmesg:显示开机信息 dmesg命令的功能说明 dmesg 命令用于显示开机信息.kernel 会将开机信息存储在 ring buffer 中. ...
- ASUS RT-AC68U 刷梅林固件及安装***插件记录(详细)
本文借鉴网络并亲自刷机过程记录(网上很多教程都不太详细) 版本:华硕ASUS RT- AC68U Wireless-AC1900 路由器的连接方式略,有说明书 连好后打开浏览器输入:http:/ ...
- property与x.setter与x.deleter
#测试property,x.setter,x.deleter class Test1: def __init__(self): self.__private = "alex" @p ...
- Go语言中的string知识点
1.Go语言String的本质就是一个[]byte,所以他们之间可以互相转换,byte数组的长度就是字符串的长度. func StringTest1() { str := "Hello,Wo ...