1 System.Threading.Tasks.Task簡介
一個Task表示一個異步操作,Task的創建和執行是獨立的。
只讀屬性:
| 返回值 |
名稱 |
說明 |
| object |
AsyncState |
表示在創建任務時傳遞給該任務的狀態數據 |
| TaskCreationOptions |
CreationOptions |
獲取用於創建此任務的 TaskCreationOptions |
|
|
CurrentId |
當前正在執行 Task 的 ID |
| AggregateException |
Exception |
獲取導致 AggregateException 提前結束的 Task。如果 Task 成功完成或尚未引發任何異常,則返回 null |
| TaskFactory |
Factory |
提供對用於創建 Task 和 Task<TResult> 的工廠方法的訪問 |
| int |
Id |
獲取此 Task 實例的 ID |
| bool |
IsCanceled |
指明此 Task 實例是否由於被取消的原因而已完成執行 |
| bool |
IsCompleted |
指明此 Task 是否已完成 |
| bool |
IsFaulted |
指明Task 是否由於未經處理異常的原因而完成 |
| TaskStatus |
Status |
獲取此任務的 TaskStatus |
2 Task狀態和生命周期
一個Task實例只會完成其生命周期一次,當Task達到它的3種可能的最終狀態之一時,它就再也回不去之前的狀態了。任務的生命周期從TaskStatus.Created狀態真正開始。
1) 初始狀態:
Task實例有三種可能的初始狀態
| 值 |
說明 |
| TaskStatus.Created |
該任務已初始化,但尚未被計划。使用Task構造函數創建Task實例時的初始狀態。 |
| TaskStatus.WaitingForActivation |
該任務正在等待 .NET Framework 基礎結構在內部將其激活並進行計划。一個任務的初始狀態,這個任務只有當其依賴的任務完成之后才會被調度。 |
| TaskStatus.WaitingToRun |
該任務已被計划執行,但尚未開始執行。使用TaskFactory.StartNew創建的任務的初始狀態。 |
2)中間狀態:
Task實例有兩種可能的中間狀態
| 值 |
說明 |
| TaskStatus.Running |
該任務正在運行,但尚未完成 |
| TaskStatus.WaitingForChildrenToComplete |
該任務已完成執行,正在隱式等待附加的子任務完成 |
3) 最終狀態:
Task實例有三種可能的最終狀態
| 值 |
說明 |
| TaskStatus.Canceled |
該任務已通過對其自身的 CancellationToken 引發 OperationCanceledException 對取消進行了確認,此時該標記處於已發送信號狀態;或者在該任務開始執行之前,已向該任務的 CancellationToken 發出了信號。Task屬性IsFaulted被設置為true |
| TaskStatus.Faulted |
由於未處理異常的原因而完成的任務。Task屬性IsCanceled被設置為true |
| TaskStatus.RunToCompletion |
已成功完成執行的任務。Task屬性IsCompleted被設置為true,IsFaulted和IsCanceled被設置為false |
3 創建並執行任務
1)public Task StartNew(Action action)
參數:
action:要異步執行的操作委托
返回值:
已啟動的 System.Threading.Tasks.Task
異常:
System.ArgumentNullException:當 action 參數為 null 時引發的異常。
2)public static Task Run(Action action)
參數:
action:表示在線程池執行的隊列的任務
返回值:
已啟動的 System.Threading.Tasks.Task
異常:
System.ArgumentNullException:當 action 參數為 null 時引發的異常。
3)public void Start()
啟動 System.Threading.Tasks.Task,並將它安排到當前的 System.Threading.Tasks.TaskScheduler中執行。
異常:
System.ObjectDisposedException:已釋放 System.Threading.Tasks.Task 實例。
System.InvalidOperationException:System.Threading.Tasks.Task 未處於有效狀態,無法啟動。 它可能已啟動、已執行或已取消,或者可能已經不支持以直接計划的方式創建。
注意:
僅使用Task的構造器來創建Task的實例並不能啟動任務,還要使用Start才能啟動任務。
4)Task.Factory.StartNew與Task.Run
Task.Factory.StartNew重載方法提供更多的參數,可以控制如何計划執行任務以及如何向調試器公開計划任務的機制和控制任務的創建和執行的可選行為。
而Task.Run提供的方法則不具有上述控制機制。
4 等待任務完成
1)public void Wait()
等待 System.Threading.Tasks.Task 完成執行過程
異常:
ObjectDisposedException:Task 對象已被釋放。
AggregateException:System.Threading.Tasks.Task 已取消或在 System.Threading.Tasks.Task 的執行期間引發了異常。如果任務已被取消,System.AggregateException將包含其 System.AggregateException.InnerExceptions 集合中的 System.OperationCanceledException。
2)public static void WaitAll(params Task[] tasks)
參數:
tasks:要等待的 Task 實例的數組
異常:
ObjectDisposedException:一個或多個 Task 中的對象 tasks 已被釋放。
ArgumentNullException:tasks 參數為 null或tasks 參數包含 null 元素。
AggregateException:在至少一個 Task 實例已取消。如果任務已被取消, AggregateException 異常包含 OperationCanceledException 中的異常其 AggregateException.InnerExceptions 集合。或在至少一個執行期間引發了異常 Task 實例。
說明:
主線程會等待作為參數傳入的任務tasks執行結束才會執行下一條語句。
3)public static int WaitAny(params Task[] tasks)
參數:
tasks:要等待的 Task 實例的數組
異常:
System.ObjectDisposedException:System.Threading.Tasks.Task 已被釋放。
System.ArgumentNullException:tasks 參數為 null。
System.ArgumentException:tasks 參數包含 null 元素。
5 取消任務
使用System.Threading.CancellationToken和System.Threading.CancellationTokenSource中斷Task的執行。
1)System.Threading.CancellationToken
傳播有關應取消操作的通知
屬性:
public bool IsCancellationRequested { get; }
方法:
public void ThrowIfCancellationRequested();
如果已請求取消此標記,則引發 System.OperationCanceledException。
異常:
System.OperationCanceledException:該標記已請求取消。
System.ObjectDisposedException:關聯的System.Threading.CancellationTokenSource已被釋放。
2) System.Threading.CancellationTokenSource
通知 System.Threading.CancellationToken,告知其應被取消
屬性:
public CancellationToken Token { get; }:獲取與此 System.Threading.CancellationTokenSource 關聯的 System.Threading.CancellationToken。
異常:
System.ObjectDisposedException:已釋放標記源。
方法:
public void Cancel():傳達取消請求。
異常:
System.ObjectDisposedException:此 System.Threading.CancellationTokenSource 已被釋放。
System.AggregateException:聚合異常包含由相關聯的 System.Threading.CancellationToken 上已注冊的回調引發的所有異常。
6 任務的返回值
1)Task類型
在第1節中已經介紹了Task。
2)Task<TResult>類型
屬性
| 定義 |
說明 |
| public static TaskFactory<TResult> Factory { get; } |
提供對用於創建 System.Threading.Tasks.Task<TResult> 實例的工廠方法的訪問。 |
| public TResult Result { get; } |
獲取此 System.Threading.Tasks.Task<TResult> 的結果值 |
方法
public Task ContinueWith(Action<Task<TResult>> continuationAction)
參數:
continuationAction:在 System.Threading.Tasks.Task<TResult> 完成時要運行的操作。在運行時,委托將作為一個參數傳遞給完成的任務。
異常:
System.ObjectDisposedException:System.Threading.Tasks.Task<TResult> 已被釋放。
System.ArgumentNullException:continuationAction 參數為 null。
注意:
- 該方法的重載方法提供了更多的控制機制。可以傳入CancellationToken、TaskContinuationOptions、TaskScheduler參數。
- 使用Task.Factory.StartNew方法,如果傳入的委托無返回值,那么方法執行的返回結果類型其實是Task<TResult>,通過Task<TResult>類型的Result 屬性可以查看返回結果。對於串聯的多個任務,若后續的任務要使用上一個任務的結果,那么Task.Factory.StartNew返回值類型必須是Task<TResult>或var。
- 返回值可以是自定義類型。
7 TaskCreationOptions (枚舉類型)
用途:控制任務創建與執行的行為。
| 值 |
說明 |
| TaskCreationOptions.None |
指定應使用默認行為 |
| TaskCreationOptions.PreferFairness |
提示 System.Threading.Tasks.TaskScheduler 以一種盡可 能公平的方式安排任務,這意味着較早安排的任務將更可能較早運行,而較晚安排運行的任務將更可能較晚運行 |
| TaskCreationOptions.LongRunning |
指定某個任務將是運行時間長、粗粒度的操作。 它會向 System.Threading.Tasks.TaskScheduler 提示,過度訂閱可能是合理的。 |
| TaskCreationOptions.AttachedToParent |
指定將任務附加到任務層次結構中的某個父級 |
| TaskCreationOptions.DenyChildAttach |
如果嘗試附有子任務到創建的任務,指定 System.InvalidOperationException 將被引發 |
| TaskCreationOptions.HideScheduler |
防止環境計划程序被視為已創建任務的當前計划程序。 這意味着像 StartNew 或 ContinueWith 創建任務的執行操作將被視為 System.Threading.Tasks.TaskScheduler.Default當前計划程序 |
8 任務計划TaskScheduler
功能:擴展任務執行計划,例如自定義任務計划程序來實現性能加速。
屬性:
| 名稱 |
說明 |
| Current |
當前正在執行的任務關聯的 TaskScheduler |
| Id |
TaskScheduler 的唯一 ID |
| MaximumConcurrencyLevel |
指示此 TaskScheduler 能夠支持的最大並發級別 |
9 串聯多個任務
1)public Task ContinueWith(Action<Task> continuationAction);
參數:
continuationAction:在 System.Threading.Tasks.Task 完成時要運行的操作。 在運行時,委托將作為一個參數傳遞給完成的任務。
異常:
System.ObjectDisposedException:創建了 cancellationToken 的 System.Threading.CancellationTokenSource 已經被釋放。
System.ArgumentNullException:continuationAction 參數為 null。
2)public Task ContinueWith(Action<Task> continuationAction, TaskContinuationOptions continuationOptions);
參數:
continuationAction:根據在 continuationOptions 中指定的條件運行的操作。 在運行時,委托將作為一個參數傳遞給完成的任務。
continuationOptions:用於設置計划延續任務的時間以及延續任務的工作方式的選項。
3)TaskContinuationOptions
enum類型,用於設置計划延續任務的時間以及延續任務的工作方式的選項。 這包括條件(如 System.Threading.Tasks.TaskContinuationOptions.OnlyOnCanceled)和執行選項(如
System.Threading.Tasks.TaskContinuationOptions.ExecuteSynchronously)。
| 值 |
說明 |
| ContinuationOptions.None |
指定應使用默認行為。默認情況下,完成前面的任務之后將安排運行延續任務,而不考慮前面任務的最終 System.Threading.Tasks.TaskStatus。
|
| ContinuationOptions.LongRunning |
指定某個任務將是運行時間長、粗粒度的操作。 它會向 System.Threading.Tasks.TaskScheduler 提示,過度訂閱可能是合理的。 |
| ContinuationOptions.AttachedToParent |
指定將任務附加到任務層次結構中的某個父級。 |
| ContinuationOptions.DenyChildAttach |
如果嘗試附有子任務到創建的任務,指定 System.InvalidOperationException 將被引發。 |
| ContinuationOptions.HideScheduler |
防止環境計划程序被視為已創建任務的當前計划程序。 這意味着像 StartNew 或 ContinueWith 創建任務的執行操作將被視為System.Threading.Tasks.TaskScheduler.Default當前計划程序。 |
| ContinuationOptions.LazyCancellation |
在延續取消的情況下,防止延續的完成直到完成先前的任務 |
| ContinuationOptions.NotOnRanToCompletion |
指定不應在延續任務前面的任務已完成運行的情況下安排延續任務。 此選項對多任務延續無效 |
| ContinuationOptions.NotOnFaulted |
指定不應在延續任務前面的任務引發了未處理異常的情況下安排延續任務。 此選項對多任務延續無效 |
| ContinuationOptions.OnlyOnCanceled |
指定只應在延續任務前面的任務已取消的情況下才安排延續任務。 此選項對多任務延續無效 |
| ContinuationOptions.NotOnCanceled |
指定不應在延續任務前面的任務已取消的情況下安排延續任務。 此選項對多任務延續無效 |
| ContinuationOptions.OnlyOnFaulted |
指定只應在延續任務前面的任務引發了未處理異常的情況下才安排延續任務。 此選項對多任務延續無效 |
| ContinuationOptions.OnlyOnRanToCompletion |
指定只應在延續任務前面的任務已完成運行的情況下才安排延續任務。 此選項對多任務延續無效 |
| ContinuationOptions.ExecuteSynchronously |
指定應同步執行延續任務。 指定此選項后,延續任務將在導致前面的任務轉換為其最終狀態的相同線程上運行。 如果在創建延續任務時已經完成前面的任務,則延續任務將在創建此延續任務的線程上運行。只應同步執行運行時間非常短的延續任務 |
| ContinuationOptions.PreferFairness |
提示 System.Threading.Tasks.TaskScheduler 以一種盡可能公平的方式安排任務,這意味着較早安排的任務將更可能較早運行,而較晚安排運行的任務將更可能較晚運行。 |
注意:
1)可以通過位操作組合使用多個值。
2)使用ContinuationOptions.None意味着不論前面的任務是否被取消,延續任務都會執行。
異常:
System.ObjectDisposedException:System.Threading.Tasks.Task 已被釋放。
System.ArgumentNullException:continuationAction 參數為 null。
System.ArgumentOutOfRangeException:continuationOptions 參數為 System.Threading.Tasks.TaskContinuationOptions 指定無效值。
3)子任務(嵌套任務):在父任務的委托中創建的 System.Threading.Tasks.Task 實例。 子任務包括兩種:附加的子任務與分離的子任務
- 分離的子任務是不依賴於其父級而執行。
- 附加的子任務是使用 TaskCreationOptions.AttachedToParent 選項創建的,依賴於其父任務而執行。 對父任務使用TaskCreationOptions.DenyChildAttach來阻止子任務附加到父任務。
- 一個任務可以創建任意數量的附加的子任務和分離的子任務,這僅受系統資源限制。
- 不提倡創建附加的子任務,這樣會大大增加程序設計的復雜性。
10 使用模式
1)創建任務
基本形式:
1 private void CreatTask() 2 { 3 //創建並執行任務 4 Task task = new Task(() => 5 { 6 //具體操作 7 }); 8 task.Start(); 9 10 //創建並將任務加入執行計划,使用StartNew 11 Task.Factory.StartNew(() => { 12 //具體操作 13 }); 14 15 //創建並將任務加入執行計划,使用Run 16 Task.Run(() => 17 { 18 //具體操作 19 }); 20 21 //安排任務 22 Task.Factory.StartNew(() => 23 { 24 //具體操作 25 },TaskCreationOptions.PreferFairness); 26 }
創建附加的子任務:
1 private void CreateTask_Parent() 2 { 3 //附加子任務 4 var taskParent = Task.Factory.StartNew(() => 5 { 6 //操作...... 7 var child = Task.Factory.StartNew(() => 8 { 9 //具體操作 10 }, TaskCreationOptions.AttachedToParent); 11 }); 12 taskParent.Wait(); 13 14 15 //阻止附加子任務 16 var taskParentZ = Task.Factory.StartNew(() => 17 { 18 //操作...... 19 var child = Task.Factory.StartNew(() => 20 { 21 //即使設置TaskCreationOptions.AttachedToParent也無法將其附加到父任務 22 //具體操作 23 }, TaskCreationOptions.AttachedToParent); 24 }, TaskCreationOptions.DenyChildAttach); 25 taskParentZ .Wait(); 26 }
2)取消任務
1 public static void CancelFromExternal_Task() 2 { 3 CancellationTokenSource cts = new CancellationTokenSource(); 4 5 //其他操作... 6 7 //計算condition 8 bool condition = ...; 9 if (condition) cts.Cancel(); 10 //或使用Operation2_Task(cts); 11 Operation1_Task(cts); 12 //其他操作... 13 14 } 15 16 //1 使用IsCancellationRequested屬性 17 private static void Operation1_Task(CancellationTokenSource cts) 18 { 19 CancellationToken ct = cts.Token; 20 Task.Factory.StartNew(() => 21 { 22 //其他操作... 23 //return只對當前子線程有效 24 if (ct.IsCancellationRequested) 25 { return; } 26 //其他操作... 27 },ct); 28 } 29 30 //2 使用拋異常的方式 31 private static void Operation2_Task(CancellationTokenSource cts) 32 { 33 CancellationToken ct = cts.Token; 34 Task.Factory.StartNew(() => 35 { 36 //其他操作... 37 ct.ThrowIfCancellationRequested(); 38 //其他操作... 39 }, ct); 40 }
3)等待任務完成
1 private void WaitFunc() 2 { 3 Task task = new Task(() => 4 { 5 //具體操作 6 }); 7 task.Start(); 8 task.Wait(); 9 } 10 11 private void WaitAllFunc() 12 { 13 Task task1 = Task.Run(() => 14 { 15 //具體操作 16 }); 17 Task task2 = Task.Run(() => 18 { 19 //具體操作 20 }); 21 //等待task1與task2,直到它們完成為止 22 Task.WaitAll(task1, task2); 23 24 //等待task1與task2,如果超過1000毫秒則返回。 25 Task.WaitAll(new Task[] { task1, task2 },1000); 26 }
4)串聯多個任務
1 private void contactTasks() 2 { 3 var t1 = Task.Factory.StartNew(() => 4 { 5 //具體操作1 6 //return 返回值; 7 }); 8 9 var t2 = t1.ContinueWith((t) => 10 { 11 //具體操作2 12 //return 返回值; 13 }); 14 15 var t3 = t2.ContinueWith((t) => 16 { 17 //具體操作3 18 }); 19 20 var t4 = t1.ContinueWith((t) => 21 { 22 //具體操作4 23 }); 24 25 var t5 = t1.ContinueWith((t) => 26 { 27 //具體操作5 28 }); 29 30 Task.WaitAll(t3, t4, t5); 31 }
-----------------------------------------------------------------------------------------
轉載與引用請注明出處。
時間倉促,水平有限,如有不當之處,歡迎指正。
