天天看點

8天玩轉并行開發——第二天 Task的使用

     在我們了解Task之前,如果我們要使用多核的功能可能就會自己來開線程,然而這種線程模型在.net 4.0之後被一種稱為基于

“任務的程式設計模型”所沖擊,因為task會比thread具有更小的性能開銷,不過大家肯定會有疑惑,任務和線程到底有什麼差別?

1:任務是架構線上程之上的,也就是說任務最終還是要抛給線程去執行。

2:任務跟線程不是一對一的關系,比如開10個任務并不是說會開10個線程,這一點任務有點類似線程池,但是任務相比線程池有很小

      的開銷和精确的控制。

一:Task

1. 最簡單的使用

  開啟task有兩種方式:

<1> 執行個體化Task

<2>從工廠中建立

是的,同樣兩種方法都可以建立,我們肯定會想兩者是不是多多少少有點差別呢?好的,下面我們舉個例子看分曉。

8天玩轉并行開發——第二天 Task的使用

①:從圖中可以看出兩種task執行個體的簡略生命周期。

Created:表示預設初始化任務,但是我們發現“工廠建立的”執行個體直接跳過。

WaitingToRun: 這種狀态表示等待任務排程器配置設定線程給任務執行。

RanToCompletion:任務執行完畢。

②:我們發現task的使用跟Thread很相似,就連waitAll的方法使用也一樣,剛才也說了,任務是架構線上程之上,那麼我們用VS裡面的

      “并行任務”看一看,快捷鍵Ctrl+D,K,或者找到“調試"->"視窗“->"并行任務“,我們在WaitAll方法處插入一個斷點,最終我們發現

      任務确實托管給了線程。

8天玩轉并行開發——第二天 Task的使用

2. 取消任務

   我們知道task是并行計算的,比如說主線程在某個時刻由于某種原因要取消某個task的執行,我們能做到嗎? 當然我們可以做到。

在4.0中給我們提供一個“取消标記”叫做CancellationTokenSource.Token,在建立task的時候傳入此參數,就可以将主線程和任務相

關聯,然後在任務中設定“取消信号“叫做ThrowIfCancellationRequested來等待主線程使用Cancel來通知,一旦cancel被調用。task将會

抛出OperationCanceledException來中斷此任務的執行,最後将目前task的Status的IsCanceled屬性設為true。看起來是不是很抽象,

沒關系,上代碼說話。

從圖中可以看出

①:Run1中的Console.WriteLine("我是任務1的第二部分資訊"); 沒有被執行。

②:Console.WriteLine("task1是不是被取消了? {0}", task1.IsCanceled); 狀态為True。

也就告訴我們Run1中途被主線程中斷執行,我們coding的代碼起到效果了。

8天玩轉并行開發——第二天 Task的使用

3. 擷取任務的傳回值

  我們以前寫線程的時候注冊的方法一般都是void類型,如果主線程要從工作線程中擷取資料一般采用的手段是“委托+事件”的模式,然而

在Task中有兩種方式可以解決。

<1>  現在我們的執行個體化是采用Task<TResult>的形式,其中TResult就是目前task執行後傳回的結果,下面舉得例子是t2任務擷取

         t1的執行結果。

8天玩轉并行開發——第二天 Task的使用

<2>采用ContinueWith方法,很有意思,現在我們将上面的方法改造一下。

8天玩轉并行開發——第二天 Task的使用

4:ContinueWith結合WaitAll來玩一把

    當這兩者結合起來,我們就可以玩一些複雜一點的東西,比如說現在有7個任務,其中t1需要串行,t2-t3可以并行,t4需要串行,t5-t6并行,

t7串行。

8天玩轉并行開發——第二天 Task的使用

好了,我們上一下代碼說話,下面代碼沒有實際意思,純屬示範。

8天玩轉并行開發——第二天 Task的使用