第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。

一. 整体说明

揭秘:

  通过F12查看Task类的源码(详见下面的截图),发现Task类的构造函数有有一个参数为:TaskCreationOptions类型,本章节可以算作是一个扩展章节,主要就来研究TaskCreationOptions类的作用。

  该类主要用来处理父子线程之间的关系,重要的几个参数如下: 

  ①.AttachedToParent:指定将任务附加到任务层次结构中的某个父级,父任务必须等待所有子任务执行完毕才能执行

    (下面的例子task线程必须等task1和task2线程执行完毕才能执行)

  ②. DenyChildAttach: 不允许子任务附加到父任务上

    (下面例子task不再等待task1和task2,和00的默认效果相同)

  ③. HideScheduler: 子任务不使用父类Task的Scheduler,而是使用默认的 (不进行测试)

  ④. LongRunning:当已知是长时间运行的任务,可以使用该选项 (不进行测试)

  ⑤. PreferFairness:类似于队列的感觉,尽可能公平的方式安排任务 (不进行测试)

 源码如下:

第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。 View Code

 

二. 实际测试

   这里我们主要通过代码来比较默认情况下、AttachedToParent、DenyChildAttach之间的效果, task线程内部有task1和task2线程,并且在task内部开启。

1. 默认情况

第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。

 1         {
 2             Stopwatch watch = new Stopwatch();
 3             watch.Start();
 4             Console.WriteLine("----------------- Task多线程测试  --------------------------");
 5             Console.WriteLine("----------------- button1_Click 开始 主线程id为:{0}  --------------------------", Thread.CurrentThread.ManagedThreadId);
 6 
 7             #region 00-默认
 8             {
 9                 Task task = new Task(() =>
10                 {
11                     Task task1 = new Task(() =>
12                     {
13                         Thread.Sleep(1000);
14                         Console.WriteLine("我是task1线程");
15                     });
16                     Task task2 = new Task(() =>
17                     {
18                         Thread.Sleep(1000);
19                         Console.WriteLine("我是task2线程");
20                     });
21 
22                     task1.Start();
23                     task2.Start();
24                 });
25 
26                 task.Start();
27                 task.Wait();   //单个线程的等待
28                 Console.WriteLine("------------------我是主线程--------------------");
29             }
30             #endregion
31 
32             watch.Stop();
33             Console.WriteLine("----------------- button1_Click 结束 主线程id为:{0}  总耗时:{1}--------------------------", Thread.CurrentThread.ManagedThreadId, watch.ElapsedMilliseconds);
34         }

第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。

  多次执行上述代码看效果:发现task线程执行完后,task1和task2才无序的执行。

第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。

2. AttachedToParent

  作用:指定将任务附加到任务层次结构中的某个父级,父任务必须等待所有子任务执行完毕才能执行

第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。

 1          {
 2                 Task task = new Task(() =>
 3                 {
 4                     Task task1 = new Task(() =>
 5                     {
 6                         Thread.Sleep(3000);
 7                         Console.WriteLine("我是task1线程");
 8                     }, TaskCreationOptions.AttachedToParent);
 9                     Task task2 = new Task(() =>
10                     {
11                         Thread.Sleep(3000);
12                         Console.WriteLine("我是task2线程");
13                     }, TaskCreationOptions.AttachedToParent);
14 
15                     task1.Start();
16                     task2.Start();
17                 });
18 
19                 task.Start();
20                 task.Wait();   //单个线程的等待
21                 Console.WriteLine("------------------我是主线程--------------------");
22             }

第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。

   多次执行上述代码看效果:发现task线程必须等task1和task2执行完毕后才能执行(印证了AttachedToParent的作用),task1和task2无先后顺序。

第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。

3. DenyChildAttach

   作用:不允许子任务附加到父任务上。

第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。

 1  {
 2                 Task task = new Task(() =>
 3                 {
 4                     Task task1 = new Task(() =>
 5                     {
 6                         Thread.Sleep(3000);
 7                         Console.WriteLine("我是task1线程");
 8                     }, TaskCreationOptions.AttachedToParent);
 9                     Task task2 = new Task(() =>
10                     {
11                         Thread.Sleep(3000);
12                         Console.WriteLine("我是task2线程");
13                     }, TaskCreationOptions.AttachedToParent);
14 
15                     task1.Start();
16                     task2.Start();
17                 }, TaskCreationOptions.DenyChildAttach);
18 
19                 task.Start();
20                 task.Wait();   //单个线程的等待
21                 Console.WriteLine("------------------我是主线程--------------------");
22             }

第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。

 多次执行上述代码看效果:发现task线程执行完后,task1和task2才无序的执行。(和上述的默认情况是一致的)

 第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。