1. 程式人生 > >C# Task任務詳解及其使用方式

C# Task任務詳解及其使用方式

1.Task類介紹:

Task 類的表示單個操作不返回一個值,通常以非同步方式執行。 Task 物件是一個的中心思想 基於任務的非同步模式 首次引入.NET Framework 4 中。 因為由執行工作 Task 物件通常以非同步方式執行線上程池執行緒上而不是以同步方式在主應用程式執行緒,您可以使用 Status 屬性,以及 IsCanceled, ,IsCompleted, ,和 IsFaulted 屬性,以確定任務的狀態。 大多數情況下,lambda 表示式用於指定的任務是執行的工作。

對於返回值的操作,您使用 Task 類。

任務Task和執行緒Thread的區別:

1、任務是架構線上程之上的,也就是說任務最終還是要拋給執行緒

去執行。

2、任務跟執行緒不是一對一的關係,比如開10個任務並不是說會開10個執行緒,這一點任務有點類似執行緒池,但是任務相比執行緒池有很小的開銷和精確的控制。

Task和Thread一樣,位於System.Threading名稱空間下!

一、建立Task

Task 類還提供了建構函式對任務進行初始化,但的未計劃的執行。 出於效能原因, Task.Run 或 TaskFactory.StartNew(工廠建立) 方法是用於建立和計劃計算的任務的首選的機制,但對於建立和計劃必須分開的方案,您可以使用的建構函式(new一個出來),然後呼叫 Task.Start 方法來計劃任務,以在稍後某個時間執行。

 //第一種建立方式,直接例項化:必須手動去Start
   var task1 = new Task(() =>
    {
       //TODO you code
    });
   task1.Start();

//第二種建立方式,工廠建立,直接執行
   var task2 = Task.Factory.StartNew(() =>
    {
     //TODO you code
    });

二、Task的簡略生命週期:

方法名 說明
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的任務控制:Task最吸引人的地方就是他的任務控制了,你可以很好的控制task的執行順序,讓多個task有序的工作

方法名 說明
Task.Wait task1.Wait();就是等待任務執行(task1)完成,task1的狀態變為Completed。
Task.WaitAll 待所有的任務都執行完成:
Task.WaitAny 發同Task.WaitAll,就是等待任何一個任務完成就繼續向下執行
Task.ContinueWith 第一個Task完成後自動啟動下一個Task,實現Task的延續
CancellationTokenSource 通過cancellation的tokens來取消一個Task。

下面詳細介紹一下上面的幾個方法:

1、Task.Wait

task1.Wait();就是等待任務執行(task1)完成,task1的狀態變為Completed。

2、Task.WaitAll

看字面意思就知道,就是等待所有的任務都執行完成:

 {
Task.WaitAll(task,task2,task3...N)
Console.WriteLine("All task finished!");
}

即當task,task2,task3…N全部任務都執行完成之後才會往下執行程式碼(打印出:“All task finished!”)

3、Task.WaitAny

這個用發同Task.WaitAll,就是等待任何一個任務完成就繼續向下執行,將上面的程式碼WaitAll替換為WaitAny

 {
Task.WaitAny(task,task2,task3...N)
Console.WriteLine("Any task finished!");
}

即當task,task2,task3…N任意一個任務都執行完成之後就會往下執行程式碼(打印出:” Any task finished!”)

4、Task.ContinueWith

就是在第一個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的返回值。

5、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. 因為任務通常執行以非同步方式線上程池執行緒上,建立並啟動任務的執行緒將繼續執行,一旦該任務已例項化。 在某些情況下,當呼叫執行緒的主應用程式執行緒,該應用程式可能會終止之前任何任務實際開始執行。 其他情況下,應用程式的邏輯可能需要呼叫執行緒繼續執行,僅當一個或多個任務執行完畢。 您可以同步呼叫執行緒的執行,以及非同步任務它啟動通過呼叫 Wait 方法來等待要完成的一個或多個任務。 若要等待完成一項任務,可以呼叫其 Task.Wait 方法。 呼叫 Wait 方法將一直阻塞呼叫執行緒直到單一類例項都已完成執行。