一. 整体说明

揭秘:

  该章节的性质和上一个章节类似,也是一个扩展的章节,主要来研究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的更多相关文章

  1. VUE2.0实现购物车和地址选配功能学习第六节

    第六节 地址列表过滤和展开所有的地址 html:<li v-for="(item,index) in filterAddress">js: new Vue({ el:' ...

  2. 第四百一十六节,Tensorflow简介与安装

    第四百一十六节,Tensorflow简介与安装 TensorFlow是什么 Tensorflow是一个Google开发的第二代机器学习系统,克服了第一代系统DistBelief仅能开发神经网络算法.难 ...

  3. 第九节: 利用RemoteScheduler实现Sheduler的远程控制 第八节: Quartz.Net五大构件之SimpleThreadPool及其四种配置方案 第六节: 六类Calander处理六种不同的时间场景 第五节: Quartz.Net五大构件之Trigger的四大触发类 第三节: Quartz.Net五大构件之Scheduler(创建、封装、基本方法等)和Job(创建、关联

    第九节: 利用RemoteScheduler实现Sheduler的远程控制   一. RemoteScheduler远程控制 1. 背景: 在A服务器上部署了一个Scheduler,我们想在B服务器上 ...

  4. CUDA:Supercomputing for the Masses (用于大量数据的超级计算)-第六节

    原文链接 第六节:全局内存和CUDA RPOFILER  Rob Farber 是西北太平洋国家实验室(Pacific Northwest National Laboratory)的高级科研人员.他在 ...

  5. 风炫安全web安全学习第三十六节课-15种上传漏洞讲解(一)

    风炫安全web安全学习第三十六节课 15种上传漏洞讲解(一) 文件上传漏洞 0x01 漏洞描述和原理 文件上传漏洞可以说是日常渗透测试用得最多的一个漏洞,因为用它获得服务器权限最快最直接.但是想真正把 ...

  6. 基于Extjs的web表单设计器 第六节——界面框架设计

    基于Extjs的web表单设计器 基于Extjs的web表单设计器 第一节 基于Extjs的web表单设计器 第二节——表单控件设计 基于Extjs的web表单设计器 第三节——控件拖放 基于Extj ...

  7. 第一百二十六节,JavaScript,XPath操作xml节点

    第一百二十六节,JavaScript,XPath操作xml节点 学习要点: 1.IE中的XPath 2.W3C中的XPath 3.XPath跨浏览器兼容 XPath是一种节点查找手段,对比之前使用标准 ...

  8. delphi 线程教学第六节:TList与泛型

    第六节: TList 与泛型   TList 是一个重要的容器,用途广泛,配合泛型,更是如虎添翼. 我们先来改进一下带泛型的 TList 基类,以便以后使用. 本例源码下载(delphi XE8版本) ...

  9. 第十六节、基于ORB的特征检测和特征匹配

    之前我们已经介绍了SIFT算法,以及SURF算法,但是由于计算速度较慢的原因.人们提出了使用ORB来替代SIFT和SURF.与前两者相比,ORB有更快的速度.ORB在2011年才首次发布.在前面小节中 ...

随机推荐

  1. PHP实现表单提交发送邮件

    只需要三个文件就可以了: 注意: 文件自命名需修改表单提交url,包含的类文件名: HTML表单文件: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML ...

  2. Starting sshd: /var/empty/sshd must be owned by root and not group or world-writable.

    Starting sshd: /var/empty/sshd must be owned by root and not group or world-writable.      [FAILED] ...

  3. kernel笔记——定时器与时间管理

    内核中时钟主要完成以下作用: 记录系统运行时间 完成时间相关的统计功能,如cpu占用率等 定时功能,设定某个进程一段时间后完成某项任务 为实现以上功能,硬件以及内核提供了不同类型的时钟. RTC 实时 ...

  4. 在Windows下使用Git+TortoiseGit+码云管理项目代码

    1.      安装Git 下载地址:点击打开链接 安装指南:默认选项即可 2.      安装TortoiseGit 下载地址:点击打开链接 安装指南:点击打开链接 3.      在码云创建账号, ...

  5. Python编码规范(PEP8)及奇技淫巧(不断更新)

    https://blog.csdn.net/MrLevo520/article/details/69155636

  6. python学习之类的反射

    在学习网络编程的时候用到反射,然后发现自己反射这部分的应用不是很熟练,决定返回来重新整理一下 对于类的反射,主要有四个用法,下面都说一下 1.hasattr 判断对象或者类是否存在指定的属性,看代码以 ...

  7. python字符串replace失效问题

    python字符串replace替换无效 背景 今天想把一个列表中符合条件的元素中 替换部分字符串, 发现怎么替换,改元素还是没有改变,本以为是内存引用的问题后来发现并不然. 经查阅解决 在Pytho ...

  8. stm32之不定长接收

    使用STM32CUBE_MAX配置工程,可以简化编程工作量,但是这样我们会遇到一些麻烦,比如利用串口接收不知道长度的数据的时候,我们可能会无从下手,前段时间看到他人程序中的串口不定长接收,此次特意总结 ...

  9. 深入理解 Java 基本数据类型

    深入理解 Java 基本数据类型

  10. 拜托!面试请不要再问我Spring Cloud底层原理

    概述 毫无疑问,Spring Cloud是目前微服务架构领域的翘楚,无数的书籍博客都在讲解这个技术.不过大多数讲解还停留在对Spring Cloud功能使用的层面,其底层的很多原理,很多人可能并不知晓 ...