https://blog.csdn.net/younghaiqing/article/details/81455410php
Task 類的表示單個操做不返回一個值,一般以異步方式執行。 Task 對象是一個的中心思想 基於任務的異步模式 首次引入.NET Framework 4 中。 由於由執行工做 Task 對象一般以異步方式執行在線程池線程上而不是以同步方式在主應用程序線程,您可使用 Status 屬性,以及 IsCanceled, ,IsCompleted, ,和 IsFaulted 屬性,以肯定任務的狀態。 大多數狀況下,lambda 表達式用於指定的任務是執行的工做。編程
對於返回值的操做,您使用 Task 類。markdown
任務Task和線程Thread的區別:多線程
一、任務是架構在線程之上的,也就是說任務最終仍是要拋給線程去執行。架構
二、任務跟線程不是一對一的關係,好比開10個任務並非說會開10個線程,這一點任務有點相似線程池,可是任務相比線程池有很小的開銷和精確的控制。異步
Task和Thread同樣,位於System.Threading命名空間下!函數
Task 類還提供了構造函數對任務進行初始化,但的未計劃的執行。 出於性能緣由, Task.Run 或 TaskFactory.StartNew(工廠建立) 方法是用於建立和計劃計算的任務的首選的機制,但對於建立和計劃必須分開的方案,您可使用的構造函數(new一個出來),而後調用 Task.Start 方法來計劃任務,以在稍後某個時間執行。post
//第一種建立方式,直接實例化:必須手動去Start var task1 = new Task(() => { //TODO you code }); task1.Start(); //第二種建立方式,工廠建立,直接執行 var task2 = Task.Factory.StartNew(() => { //TODO you code });
方法名 | 說明 |
---|---|
Created | 表示默認初始化任務,可是「工廠建立的」實例直接跳過。 |
WaitingToRun | 這種狀態表示等待任務調度器分配線程給任務執行。 |
RanToCompletion | 任務執行完畢。 |
//查看Task中的狀態 var task1 = new Task(() => { Console.WriteLine("Begin"); System.Threading.Thread.Sleep(2000); Console.WriteLine("Finish"); }); Console.WriteLine("Before start:" + task1.Status); task1.Start(); Console.WriteLine("After start:" + task1.Status); task1.Wait(); Console.WriteLine("After Finish:" + task1.Status); Console.Read();
方法名 | 說明 |
---|---|
Task.Wait | task1.Wait();就是等待任務執行(task1)完成,task1的狀態變爲Completed。 |
Task.WaitAll | 待全部的任務都執行完成: |
Task.WaitAny | 發同Task.WaitAll,就是等待任何一個任務完成就繼續向下執行 |
Task.ContinueWith | 第一個Task完成後自動啓動下一個Task,實現Task的延續 |
CancellationTokenSource | 經過cancellation的tokens來取消一個Task。 |
下面詳細介紹一下上面的幾個方法:性能
task1.Wait();就是等待任務執行(task1)完成,task1的狀態變爲Completed。
看字面意思就知道,就是等待全部的任務都執行完成:
{
Task.WaitAll(task,task2,task3...N) Console.WriteLine("All task finished!"); }
即當task,task2,task3…N所有任務都執行完成以後纔會往下執行代碼(打印出:「All task finished!」)
這個用發同Task.WaitAll,就是等待任何一個任務完成就繼續向下執行,將上面的代碼WaitAll替換爲WaitAny
{
Task.WaitAny(task,task2,task3...N) Console.WriteLine("Any task finished!"); }
即當task,task2,task3…N任意一個任務都執行完成以後就會往下執行代碼(打印出:」 Any task finished!」)
就是在第一個Task完成後自動啓動下一個Task,實現Task的延續,下面咱們來看下他的用法,編寫以下代碼:
static void Main(string[] args) { var task1 = new Task(() => { Console.WriteLine("Task 1 Begin"); System.Threading.Thread.Sleep(2000); Console.WriteLine("Task 1 Finish"); }); var task2 = new Task(() => { Console.WriteLine("Task 2 Begin"); System.Threading.Thread.Sleep(3000); Console.WriteLine("Task 2 Finish"); }); task1.Start(); task2.Start(); var result = task1.ContinueWith<string>(task => { Console.WriteLine("task1 finished!"); return "This is task result!"; }); Console.WriteLine(result.Result.ToString()); Console.Read(); }
能夠看到,task1完成以後,開始執行後面的內容,而且這裏咱們取得task的返回值。
前面說了那麼多Task的用法,下面來講下Task的取消,好比咱們啓動了一個task,出現異常或者用戶點擊取消等等,咱們能夠取消這個任務。如何取消一個Task呢,咱們經過cancellation的tokens來取消一個Task。在不少Task的Body裏面包含循環,咱們能夠在輪詢的時候判斷IsCancellationRequested屬性是否爲True,若是是True的話就return或者拋出異常,拋出異常後面再說,由於尚未說異常處理的東西。
下面在代碼中看下如何實現任務的取消,代碼以下:
var tokenSource = new CancellationTokenSource(); var token = tokenSource.Token; var task = Task.Factory.StartNew(() => { for (var i = 0; i < 1000; i++) { System.Threading.Thread.Sleep(1000); if (token.IsCancellationRequested) { Console.WriteLine("Abort mission success!"); return; } } }, token); token.Register(() => { Console.WriteLine("Canceled"); }); Console.WriteLine("Press enter to cancel task..."); Console.ReadKey(); tokenSource.Cancel();
這裏開啓了一個Task,並給token註冊了一個方法,輸出一條信息,而後執行ReadKey開始等待用戶輸入,用戶點擊回車後,執行tokenSource.Cancel方法,取消任務。
參考文獻:
1.http://www.javashuo.com/article/p-cpizczev-bb.html
2.https://msdn.microsoft.com/zh-cn/library/system.threading.tasks.task.aspx?cs-save-lang=1&cs-lang=csharp#code-snippet-1
using System; using System.Threading.Tasks; using System.Threading; namespace 實現取消選項 { class Program { static void Main(string[] args) { var cts = new CancellationTokenSource(); var longTask = new Task<int>(() => TaskMethod("Task 1", 10, cts.Token), cts.Token); Console.WriteLine(longTask.Status); cts.Cancel(); Console.WriteLine(longTask.Status); Console.WriteLine("First task has been cancelled before execution"); cts = new CancellationTokenSource(); longTask = new Task<int>(() => TaskMethod("Task 2", 10, cts.Token), cts.Token); longTask.Start(); for (int i = 0; i < 5; i++) { Thread.Sleep(TimeSpan.FromSeconds(0.5)); Console.WriteLine(longTask.Status); } cts.Cancel(); for (int i = 0; i < 5; i++) { Thread.Sleep(TimeSpan.FromSeconds(0.5)); Console.WriteLine(longTask.Status); } Console.WriteLine("A task has been completed with result {0}.", longTask.Result); Console.ReadKey(); } private static int TaskMethod(string name,int seconds,CancellationToken token) { Console.WriteLine("Task {0} is running on a thread id {1},Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); for (int i = 0; i < seconds; i++) { Thread.Sleep(TimeSpan.FromSeconds(1)); if (token.IsCancellationRequested) { Console.WriteLine("Cancel Task {0} is running on a thread id {1},Is thread pool thread: {2}", name, Thread.CurrentThread.ManagedThreadId, Thread.CurrentThread.IsThreadPoolThread); return -1; } } return 42 * seconds; } } }