第六节:深入研究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不能执行)

 源码如下:

复制代码

 1  [Serializable]2     [Flags]3     public enum TaskContinuationOptions4     {5         // 摘要: 6         //     Default = "Continue on any, no task options, run asynchronously" 指定应使用默认行为。7         //     默认情况下,完成前面的任务之后将安排运行延续任务,而不考虑前面任务的最终 System.Threading.Tasks.TaskStatus。8         None = 0,9         //
10         // 摘要: 
11         //     提示 System.Threading.Tasks.TaskScheduler 以一种尽可能公平的方式安排任务,这意味着较早安排的任务将更可能较早运行,而较晚安排运行的任务将更可能较晚运行。
12         PreferFairness = 1,
13         //
14         // 摘要: 
15         //     指定某个任务将是运行时间长、粗粒度的操作。 它会向 System.Threading.Tasks.TaskScheduler 提示,过度订阅可能是合理的。
16         LongRunning = 2,
17         //
18         // 摘要: 
19         //     指定将任务附加到任务层次结构中的某个父级。
20         AttachedToParent = 4,
21         //
22         // 摘要: 
23         //     如果尝试附有子任务到创建的任务,指定 System.InvalidOperationException 将被引发。
24         DenyChildAttach = 8,
25         //
26         // 摘要: 
27         //     防止环境计划程序被视为已创建任务的当前计划程序。 这意味着像 StartNew 或 ContinueWith 创建任务的执行操作将被视为 System.Threading.Tasks.TaskScheduler.Default
28         //     当前计划程序。
29         HideScheduler = 16,
30         //
31         // 摘要: 
32         //     在延续取消的情况下,防止延续的完成直到完成先前的任务。
33         LazyCancellation = 32,
34         //
35         // 摘要: 
36         //     指定不应在延续任务前面的任务已完成运行的情况下安排延续任务。 此选项对多任务延续无效。
37         NotOnRanToCompletion = 65536,
38         //
39         // 摘要: 
40         //     指定不应在延续任务前面的任务引发了未处理异常的情况下安排延续任务。 此选项对多任务延续无效。
41         NotOnFaulted = 131072,
42         //
43         // 摘要: 
44         //     指定只应在延续任务前面的任务已取消的情况下才安排延续任务。 此选项对多任务延续无效。
45         OnlyOnCanceled = 196608,
46         //
47         // 摘要: 
48         //     指定不应在延续任务前面的任务已取消的情况下安排延续任务。 此选项对多任务延续无效。
49         NotOnCanceled = 262144,
50         //
51         // 摘要: 
52         //     指定只应在延续任务前面的任务引发了未处理异常的情况下才安排延续任务。 此选项对多任务延续无效。
53         OnlyOnFaulted = 327680,
54         //
55         // 摘要: 
56         //     指定只应在延续任务前面的任务已完成运行的情况下才安排延续任务。 此选项对多任务延续无效。
57         OnlyOnRanToCompletion = 393216,
58         //
59         // 摘要: 
60         //     指定应同步执行延续任务。 指定此选项后,延续任务将在导致前面的任务转换为其最终状态的相同线程上运行。 如果在创建延续任务时已经完成前面的任务,则延续任务将在创建此延续任务的线程上运行。
61         //     只应同步执行运行时间非常短的延续任务。
62         ExecuteSynchronously = 524288,
63     }

复制代码

 

二. 实际测试

   下面通过代码来说明默认情况下、LazyCancellation、ExecuteSynchronously、NotOnRanToCompletion和OnlyOnRanToCompletion的作用和效果。

1. 默认情况

   默认情况下,task1执行完后→task2→task2执行完后→task3。  

复制代码

 1             {2                 Task task1 = new Task(() =>3                 {4                     Thread.Sleep(1000);5                     Console.WriteLine("task1 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);6                 });7 8                 var task2 = task1.ContinueWith(t =>9                 {
10                     Console.WriteLine("task2 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
11                 });
12 
13                 var task3 = task2.ContinueWith(t =>
14                 {
15                     Console.WriteLine("task3 tid={0}, dt={1}  {2}", Thread.CurrentThread.ManagedThreadId, DateTime.Now, task2.Status);
16                 });
17 
18                 task1.Start();
19 
20             }

复制代码

 运行结果: task1执行完后→ task2执行→task2执行完后→ task3执行。

2. LazyCancellation

   作用:取消该线程,该线程的前一个线程和后一个线程并行执行。

复制代码

 1             {2                 CancellationTokenSource source = new CancellationTokenSource();3                 source.Cancel();4 5                 Task task1 = new Task(() =>6                 {7                     Thread.Sleep(1000);8                     Console.WriteLine("task1 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);9                 });
10 
11                 var task2 = task1.ContinueWith(t =>
12                 {
13                     Console.WriteLine("task2 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
14                 }, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Current);
15 
16                 var task3 = task2.ContinueWith(t =>
17                 {
18                     Console.WriteLine("task3 tid={0}, dt={1}  {2}", Thread.CurrentThread.ManagedThreadId, DateTime.Now, task2.Status);
19                 });
20 
21                 task1.Start();
22 
23             }

复制代码

  运行结果: task2线程已经被取消,task1线程和task2线程并行执行。

3. ExecuteSynchronously

   作用:希望执行前面那个task的thread也在执行本延续任务。

复制代码

 1   {2                 Task task1 = new Task(() =>3                 {4                     Thread.Sleep(1000);5                     Console.WriteLine("task1 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);6                 });7 8                 var task2 = task1.ContinueWith(t =>9                 {
10                     Console.WriteLine("task2 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);
11                 }, TaskContinuationOptions.ExecuteSynchronously);
12 
13                 task1.Start();
14 }

复制代码

   结果:task1和task2线程的线程id相同。

4. NotOnRanToCompletion和OnlyOnRanToCompletion 

  NotOnRanToCompletion:延续任务必须在前面task非完成状态才能执行。

  OnlyOnRanToCompletion:延续任务必须在前面task完成状态才能执行。

复制代码

     {Task task1 = new Task(() =>{Thread.Sleep(1000);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正常时的运行结果:

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438257.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第七节:利用CancellationTokenSource实现任务取消和利用CancellationToken类检测取消异常。

一. 传统的线程取消 所谓的线程取消,就是线程正在执行的过程中取消线程任务。 传统的线程取消,是通过一个变量来控制,但是这种方式,在release模式下,被优化从cpu高速缓存中读取,而不是从内存中读取&#xf…

第八节:Task的各类TaskTResult返回值以及通用线程的异常处理方案。

一. Task的各种返回值-Task<TResult> PS&#xff1a; 在前面章节&#xff0c;我们介绍了Task类开启线程、线程等待、线程延续的方式&#xff0c;但我们并没有关注这些方式的返回值&#xff0c;其实他们都是有返回值的Task<TResult>&#xff0c;然后可以通过Task的…

第九节:深究并行编程Parallel类中的三大方法 (For、ForEach、Invoke)和几大编程模型(SPM、APM、EAP、TAP)

一. 并行编程 1. 区分串行编程和串行编程 ①. 串行编程&#xff1a;所谓的串行编程就是单线程的作用下&#xff0c;按顺序执行。(典型代表for循环 下面例子从1-100按顺序执行) ②. 并行编程&#xff1a;充分利用多核cpu的优势&#xff0c;同时开启多个线程并行执行。(典型代表…

第十节:利用async和await简化异步编程模式的几种写法

一. async和await简介 PS&#xff1a;简介 1. async和await这两个关键字是为了简化异步编程模型而诞生的&#xff0c;使的异步编程更简洁&#xff0c;它本身并不创建新线程&#xff0c;但在该方法内部开启多线程&#xff0c;则另算。 2. 这两个关键字适用于处理一些文件IO操作。…

第十一节:深究用户模式锁的使用场景(异变结构、互锁、旋转锁)

一. 锁机制的背景介绍 本章节&#xff0c;将结合多线程来介绍锁机制&#xff0c; 那么问题来了&#xff0c;什么是锁呢&#xff1f; 为什么需要锁&#xff1f; 为什么要结合多线程来介绍锁呢&#xff1f;锁的使用场景又是什么呢&#xff1f; DotNet中又有哪些锁呢&#xff1f; …

第十三节:实际开发中使用最多的监视锁Monitor、lock语法糖的扩展、混合锁的使用(ManualResetEvent、SemaphoreSlim、ReaderWriterLockSlim)

一. 监视锁(Monitor和lock) 1. Monitor类&#xff0c;限定线程个数的一把锁&#xff08;Synchronized lock是他的语法糖&#xff09;&#xff0c;两个核心方法&#xff1a; Enter&#xff1a;锁住某个资源。 Exit&#xff1a;退出某一个资源。 测试案例&#xff1a;开启5个线…

第十四节: 介绍四大并发集合类并结合单例模式下的队列来说明线程安全和非安全的场景及补充性能调优问题。

一. 四大并发集合类 背景&#xff1a;我们目前使用的所有集合都是线程不安全的 。 A. ConcurrentBag&#xff1a;就是利用线程槽来分摊Bag中的所有数据&#xff0c;链表的头插法,0代表移除最后一个插入的值. (等价于同步中的List) B. ConcurrentStack&#xff1a;线程安全的St…

第十五节:深入理解async和await的作用及各种适用场景和用法

一. 同步VS异步 1. 同步 VS 异步 VS 多线程 同步方法&#xff1a;调用时需要等待返回结果&#xff0c;才可以继续往下执行业务 异步方法&#xff1a;调用时无须等待返回结果&#xff0c;可以继续往下执行业务 开启新线程&#xff1a;在主线程之外开启一个新的线程去执行业…

@PostConstruct注解

PostConstruct是Java自己的注解. PostConstruct该注解被用来修饰一个非静态的void()方法. PostConstruct修饰的方法会在服务器加载Servlet的时候运行,并且只会被服务器执行一次. PostConstruct在构造函数之后执行,init()方法之前执行. 执行顺序 Constructor >> Autow…

springCloud五大组件--Gateway

SpringCloud Gateway 是 Spring Cloud 的一个全新项目&#xff0c;该项目是基于 Spring 5.0&#xff0c;Spring Boot 2.0 和 Project Reactor 等技术开发的网关&#xff0c;它旨在为微服务架构提供一种简单有效的统一的 API 路由管理方式。 Spring Cloud Gateway 的目标&#…

多线程篇(被替换)

一. 背景 在刚接触开发的头几年里&#xff0c;说实话&#xff0c;根本不考虑多线程的这个问题&#xff0c;貌似那时候脑子里也有没有多线程的这个概念&#xff0c;所有的业务都是一个线程来处理&#xff0c;不考虑性能问题&#xff0c;当然也没有考虑多线程操作一条记录存在的并…

springCloud五大组件--Eureka

Spring Cloud 支持了 Zookeeper、Consul 和 Eureka&#xff0c;官方推荐 Eureka。 C(一致性)A(高可用)P(分区容错)理论&#xff0c;Eureka的选择就是放弃C&#xff0c;选择AP。 Eureka 采用纯 Java 实现&#xff0c;除实现了注册中心基本的服务注册和发现之外&#xff0c;极大…

.NET异步程序设计之任务并行库

目录 1.简介2.Parallel类 2.0 Parallel类简介2.1 Parallel.For()2.2 Parallel.ForEach()2.3 Parallel.Invoke()2.4 补充&#xff1a;线程安全集合3.Task类 3.0 Task类简介3.1 创建无返回值的Task任务3.2 创建有返回值的Task任务3.3 为Task添加延续任务3.4 Task.Delay3.5 Task对…

Mysql主从延时解决办法

1.忍受大法 第一种解决办法&#xff0c;很简单&#xff0c;无他&#xff0c;不管他&#xff0c;没有读到也没事。这时业务不需要任何改造&#xff0c;你好&#xff0c;我好&#xff0c;她也好~ 如果业务对于数据一致性要求不高&#xff0c;我们就可以采用这种方案。 2.数据同…

关于C#程序的单元测试

目录 1.单元测试概念2.单元测试的原则3.单元测试简单示例4.单元测试框架特性标签5.单元测试中的断言Assert6.单元测试中验证预期的异常7.单元测试中针对状态的间接测试8.单元测试在MVC模式中的实现8.单元测试相关参考9.示例源代码下载 志铭-2020年1月23日 11:49:41 1.单元测试…

NuGet是什么?理解与使用(上)

如果你了解python&#xff0c;那么它类似pip。 如果你了解nodejs&#xff0c;那么它类似npm。 如果你了解ruby&#xff0c;那么它类似gem。 对&#xff0c;它就是一个包&#xff08;package&#xff09;管理平台&#xff0c;确切的说是 .net平台的包管理工具&#xff0c;它提…

NuGet是什么?理解与使用(下)

本篇将回答下面几个问题&#xff1a; 如何解读NuGet Gallery上的包信息&#xff1f;如何上传NuGet包到NuGet Gallery&#xff1f;如何安装本地NuGet包&#xff1f;NuGet包的内容文件与目录结构&#xff1f; 如果你没看过上篇那么它在这里&#xff1a; 6号咸鱼&#xff1a;NuG…

C#多线程之旅(1)——介绍和基本概念

阅读目录 一、多线程介绍二、Join 和Sleep三、线程怎样工作四、线程和进程五、线程的使用和误用一、多线程介绍 C#通过多线程支持并行执行的代码。一个线程是一个独立执行的路径&#xff0c;可以同时与其他线程一起运行。一个C#客户端程序(Console,WPF,Winows Forms)开始于一个…

C#多线程之旅(2)——详解线程的开始和创建

阅读目录 代码下载一、线程的创建和开始二、传递数据给一个线程三、命名线程四、前台线程和后台线程五、线程优先级六、异常处理代码下载 Thread_博客园_cnblogs_jackson0714.zip 第一篇~第三篇的代码示例&#xff1a; 源码地址&#xff1a;https://github.com/Jackson0714/T…

C#多线程之旅(3)——线程池

阅读目录 代码下载一、介绍二、通过TPL进入线程池三、不用TPL进入到线程池v博客前言 先交代下背景&#xff0c;写《C#多线程之旅》这个系列文章主要是因为以下几个原因&#xff1a;1.多线程在C/S和B/S架构中用得是非常多的;2.而且多线程的使用是非常复杂的&#xff0c;如果没有…