在我們了解Task之前,如果我們要使用多核的功能可能就會自己來開線程,然而這種線程模型在.net 4.0之後被一種稱為基于
“任務的程式設計模型”所沖擊,因為task會比thread具有更小的性能開銷,不過大家肯定會有疑惑,任務和線程到底有什麼差別?
1:任務是架構線上程之上的,也就是說任務最終還是要抛給線程去執行。
2:任務跟線程不是一對一的關系,比如開10個任務并不是說會開10個線程,這一點任務有點類似線程池,但是任務相比線程池有很小
的開銷和精确的控制。
一:Task
1. 最簡單的使用
開啟task有兩種方式:
<1> 執行個體化Task
<2>從工廠中建立
是的,同樣兩種方法都可以建立,我們肯定會想兩者是不是多多少少有點差別呢?好的,下面我們舉個例子看分曉。
①:從圖中可以看出兩種task執行個體的簡略生命周期。
Created:表示預設初始化任務,但是我們發現“工廠建立的”執行個體直接跳過。
WaitingToRun: 這種狀态表示等待任務排程器配置設定線程給任務執行。
RanToCompletion:任務執行完畢。
②:我們發現task的使用跟Thread很相似,就連waitAll的方法使用也一樣,剛才也說了,任務是架構線上程之上,那麼我們用VS裡面的
“并行任務”看一看,快捷鍵Ctrl+D,K,或者找到“調試"->"視窗“->"并行任務“,我們在WaitAll方法處插入一個斷點,最終我們發現
任務确實托管給了線程。
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的代碼起到效果了。
3. 擷取任務的傳回值
我們以前寫線程的時候注冊的方法一般都是void類型,如果主線程要從工作線程中擷取資料一般采用的手段是“委托+事件”的模式,然而
在Task中有兩種方式可以解決。
<1> 現在我們的執行個體化是采用Task<TResult>的形式,其中TResult就是目前task執行後傳回的結果,下面舉得例子是t2任務擷取
t1的執行結果。
<2>采用ContinueWith方法,很有意思,現在我們将上面的方法改造一下。
4:ContinueWith結合WaitAll來玩一把
當這兩者結合起來,我們就可以玩一些複雜一點的東西,比如說現在有7個任務,其中t1需要串行,t2-t3可以并行,t4需要串行,t5-t6并行,
t7串行。
好了,我們上一下代碼說話,下面代碼沒有實際意思,純屬示範。