zoukankan      html  css  js  c++  java
  • 第五节:Task构造函数之TaskCreationOptions枚举处理父子线程之间的关系。

    一. 整体说明

    揭秘:

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

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

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

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

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

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

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

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

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

     源码如下:

     1  // 摘要: 
     2     //     指定可控制任务的创建和执行的可选行为的标志。
     3     [Serializable]
     4     [Flags]
     5     public enum TaskCreationOptions
     6     {
     7         // 摘要: 
     8         //     指定应使用默认行为。
     9         None = 0,
    10         //
    11         // 摘要: 
    12         //     提示 System.Threading.Tasks.TaskScheduler 以一种尽可能公平的方式安排任务,这意味着较早安排的任务将更可能较早运行,而较晚安排运行的任务将更可能较晚运行。
    13         PreferFairness = 1,
    14         //
    15         // 摘要: 
    16         //     指定某个任务将是运行时间长、粗粒度的操作。 它会向 System.Threading.Tasks.TaskScheduler 提示,过度订阅可能是合理的。
    17         LongRunning = 2,
    18         //
    19         // 摘要: 
    20         //     指定将任务附加到任务层次结构中的某个父级。
    21         AttachedToParent = 4,
    22         //
    23         // 摘要: 
    24         //     如果尝试附有子任务到创建的任务,指定 System.InvalidOperationException 将被引发。
    25         DenyChildAttach = 8,
    26         //
    27         // 摘要: 
    28         //     防止环境计划程序被视为已创建任务的当前计划程序。 这意味着像 StartNew 或 ContinueWith 创建任务的执行操作将被视为 System.Threading.Tasks.TaskScheduler.Default
    29         //     当前计划程序。
    30         HideScheduler = 16,
    31     }
    View Code

    二. 实际测试

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

    1. 默认情况

     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线程执行完后,task1和task2才无序的执行。

    2. AttachedToParent

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

     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线程必须等task1和task2执行完毕后才能执行(印证了AttachedToParent的作用),task1和task2无先后顺序

    3. DenyChildAttach

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

     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线程执行完后,task1和task2才无序的执行。(和上述的默认情况是一致的)

     

  • 相关阅读:
    10.28
    10.25
    10.21
    移动第七次作业
    移动第六次作业
    移动第五次作业
    移动第四次作业
    移动第3次作业
    移动第二次作业
    移动第一次作业
  • 原文地址:https://www.cnblogs.com/yaopengfei/p/8205337.html
Copyright © 2011-2022 走看看