第五節: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才無序的執行。(和上述的默認情況是一致的)

 

 

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM