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

https://blog.csdn.net/younghaiqing/article/details/81455410php

1.Task類介紹:

Task 類的表示單個操做不返回一個值,一般以異步方式執行。 Task 對象是一個的中心思想 基於任務的異步模式 首次引入.NET Framework 4 中。 由於由執行工做 Task 對象一般以異步方式執行在線程池線程上而不是以同步方式在主應用程序線程,您可使用 Status 屬性,以及 IsCanceled, ,IsCompleted, ,和 IsFaulted 屬性,以肯定任務的狀態。 大多數狀況下,lambda 表達式用於指定的任務是執行的工做。編程

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

任務Task和線程Thread的區別:多線程

一、任務是架構在線程之上的,也就是說任務最終仍是要拋給線程去執行。架構

二、任務跟線程不是一對一的關係,好比開10個任務並非說會開10個線程,這一點任務有點相似線程池,可是任務相比線程池有很小的開銷和精確的控制。異步

Task和Thread同樣,位於System.Threading命名空間下!函數

1、建立Task

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 });

2、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();

3、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。

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

一、Task.Wait

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

二、Task.WaitAll

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

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

即當task,task2,task3…N所有任務都執行完成以後纔會往下執行代碼(打印出:「All task finished!」)

三、Task.WaitAny

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

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

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

四、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的返回值。

五、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 方法將一直阻塞調用線程直到單一類實例都已完成執行。

參考文獻: 
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;
        }
    }
}
相關文章
相關標籤/搜索