C#中TASK類的使用

然而镇饺,在今天這篇博客中匙睹,我們要知道的是,QueueUserWorkItem這個技術存在許多限制瑟由。其中最大的問題是沒有一個內(nèi)建的機制讓你知道操作在什么時候完成絮重,也沒有一個機制在操作完成是獲得一個返回值,這些問題使得我們都不敢啟用這個技術。

Microsoft為了克服這些限制(同時解決其他一些問題)青伤,引入了任務(tasks)的概念督怜。順帶說一下我們得通過System.Threading.Tasks命名空間來使用它們。

現(xiàn)在我要說的是狠角,用線程池不是調(diào)用ThreadPool的QueueUserWorkItem方法号杠,而是用任務來做相同的事:

復制代碼 1? ? ? ? static void Main(string[] args)?

2? ? ? ? {?

3? ? ? ? ? ? Console.WriteLine("主線程啟動");?

4? ? ? ? ? ? //ThreadPool.QueueUserWorkItem(StartCode,5);?

5? ? ? ? ? ? new Task(StartCode, 5).Start();

?6? ? ? ? ? ? Console.WriteLine("主線程運行到此!");?

7? ? ? ? ? ? Thread.Sleep(1000);?

8? ? ? ? }?

9 10? ? ? ? private static void StartCode(object i)

11? ? ? ? {

12? ? ? ? ? ? Console.WriteLine("開始執(zhí)行子線程...{0}",i);

13? ? ? ? ? ? Thread.Sleep(1000);//模擬代碼操作? ?

?14? ? ? ? }

15? ? }

嘿丰歌,你會發(fā)現(xiàn)結果是一樣的姨蟋。再來看看這個是什么:TaskCreationOptions這個類型是一個枚舉類型,傳遞一些標志來控制Task的執(zhí)行方式立帖。TaskCreationOptions定義如下:慢點眼溶,注釋很詳細,看看這些有好處晓勇,TaskScheduler(任務調(diào)度器)不懂沒關系堂飞,請繼續(xù)往下看,我會介紹的绑咱,但請注意绰筛,這些標識都只是一些提議而已,在調(diào)度一個Task時羡玛,可能會、也可能不會采納這些提議宗苍,不過有一條要注意:AttachedToParent標志稼稿,它總會得到Task采納,因為它和TaskScheduler本身無關讳窟。

來看下這段代碼:

1? ? ? ? static void Main(string[] args)?

2? ? ? ? {?

3? ? ? ? ? ??

? 4? ? ? ? ? ? //1000000000這個數(shù)字會拋出System.AggregateException?

5??

6? ? ? ? ? ? Taskt = new Task(n => Sum((Int32)n), 1000000000);?

7?

?8? ? ? ? ? ? //可以現(xiàn)在開始让歼,也可以以后開始??

9 10? ? ? ? ? ? t.Start();

11 12? ? ? ? ? ? //Wait顯式的等待一個線程完成

13 14? ? ? ? ? ? t.Wait();

15? ? ? ? ? ? 16? ? ? ? ? ? Console.WriteLine("The Sum is:"+t.Result);

17? ? ? ? }

18 19? ? ? ? private static Int32 Sum(Int32 i)

20? ? ? ? {

21? ? ? ? ? ? Int32 sum = 0;

22? ? ? ? ? ? for (; i > 0; i--)

23? ? ? ? ? ? ? ? checked { sum += i; }

24? ? ? ? ? ? return sum;

25? ? ? ? }

26? ? }

 這段代碼大家應該猜得出是什么意思吧,人人都會寫丽啡∧庇遥  但是,我的結果為什么是t.Result而不直接是返回的Sum呢补箍?? 有沒有多此一舉的感覺改执?下面我來說說這段代碼我想表達的意思:  在一個線程調(diào)用Wait方法時,系統(tǒng)會檢查線程要等待的Task是否已經(jīng)開始執(zhí)行坑雅,如果任務正在執(zhí)行辈挂,那么這個Wait方法會使線程阻塞,知道Task運行結束為止裹粤≈盏伲  就說上面的程序執(zhí)行,因為累加數(shù)字太大,它拋出算術運算溢出錯誤拇泣,在一個計算限制任務拋出一個未處理的異常時噪叙,這個異常會被“包含”不并存儲到一個集合中,而線程池線程是允許返回到線程池中的霉翔,在調(diào)用Wait方法或者Result屬性時睁蕾,這個成員會拋出一個System.AggregateException對象≡绻辏  現(xiàn)在你會問惫霸,為什么要調(diào)用Wait或者Result?或者一直不查詢Task的Exception屬性葱弟?你的代碼就永遠注意不到這個異常的發(fā)生壹店,如果不能捕捉到這個異常,垃圾回收時芝加,拋出AggregateException冯乘,進程就會立即終止兰绣,這就是“牽一發(fā)動全身”,莫名其妙程序就自己關掉了,誰也不知道這是什么情況效扫。所以,必須調(diào)用前面提到的某個成員莉恼,確保代碼注意到異常咕村,并從異常中恢復。悄悄告訴你来吩,其實在用Result的時候敢辩,內(nèi)部會調(diào)用Wait〉芙  怎么恢復戚长?  為了幫助你檢測沒有注意到的異常,可以向TaskScheduler的靜態(tài)UnobservedTaskException時間等級一個回調(diào)方法怠苔,當Task被垃圾回收時同廉,如果出現(xiàn)一個沒有被注意到的異常,CLR終結器會引發(fā)這個事件柑司。一旦引發(fā)迫肖,就會向你的時間處理器方法傳遞一個UnobservedTaskExceptionEvenArgs對象,其中包含了你沒有注意的AggregateException攒驰。然后再調(diào)用UnobservedTasExceptionEvenArgs的SetObserved方法來指出你的異常已經(jīng)處理好了咒程,從而阻止CLR終止進程。這是個圖省事的做法讼育,要少做這些帐姻,寧愿終止進程稠集,也不要呆著已經(jīng)損壞的狀態(tài)而繼續(xù)運行。做人也一樣饥瓷,病了寧肯休息剥纷,也不要帶病堅持上班,你沒那么偉大呢铆,公司也不需要你的這一點偉大,命是自己的晦鞋。(─.─|||扯遠了」卓耍  除了單個等待任務悠垛,Task 還提供了兩個靜態(tài)方法:WaitAny和WaitAll,他們允許線程等待一個Task對象數(shù)組娜谊∪仿颍  WaitAny方法會阻塞調(diào)用線程,知道數(shù)組中的任何一個Task對象完成纱皆,這個方法會返回一個索引值湾趾,指明完成的是哪一個Task對象。如果發(fā)生超時派草,方法將返回-1搀缠。它可以通過一個CancellationToken取消,會拋出一個OperationCanceledException近迁∫掌眨  WaitAll方法也會阻塞調(diào)用線程,知道數(shù)組中的所有Task對象都完成鉴竭,如果全部完成就返回true歧譬,如果超時就返回false。當然它也能取消拓瞪,同樣會拋出OperationCanceledException缴罗≈觯  說了這么兩個取消任務的方法祭埂,現(xiàn)在來試試這個方法,加深下印象兵钮,修改先前例子代碼蛆橡,完整代碼如下:

?1? ? ? ? static void Main(string[] args)?

2? ? ? ? {?

3? ? ? ? ? ? CancellationTokenSource cts = new CancellationTokenSource();

?4? ? ? ? ? ??

? 5? ? ? ? ? ? ??

6? 7? ? ? ? ? ? Taskt = new Task(() => Sum(cts.Token,10000), cts.Token);?

8? 9? ? ? ? ? ? //可以現(xiàn)在開始,也可以以后開始?

10? ? ? ? ? ? 11? ? ? ? ? ? t.Start();

12 13? ? ? ? ? ? //在之后的某個時間掘譬,取消CancellationTokenSource 以取消Task

14 15? ? ? ? ? ? cts.Cancel();//這是個異步請求泰演,Task可能已經(jīng)完成了。我是雙核機器葱轩,Task沒有完成過

16 17 18? ? ? ? ? ? //注釋這個為了測試拋出的異常

19? ? ? ? ? ? //Console.WriteLine("This sum is:" + t.Result);

20? ? ? ? ? ? try

21? ? ? ? ? ? {

22? ? ? ? ? ? ? ? //如果任務已經(jīng)取消了睦焕,Result會拋出AggregateException

23 24? ? ? ? ? ? ? ? Console.WriteLine("This sum is:" + t.Result);

25? ? ? ? ? ? }

26? ? ? ? ? ? catch (AggregateException x)

27? ? ? ? ? ? {

28? ? ? ? ? ? ? ? //將任何OperationCanceledException對象都視為已處理藐握。

29? ? ? ? ? ? ? ? //其他任何異常都造成拋出一個AggregateException,其中

30? ? ? ? ? ? ? ? //只包含未處理的異常

31 32? ? ? ? ? ? ? ? x.Handle(e => e is OperationCanceledException);

33? ? ? ? ? ? ? ? Console.WriteLine("Sum was Canceled");

34? ? ? ? ? ? }

35? ? ? ? ? 36? ? ? ? }

37 38? ? ? ? private static Int32 Sum(CancellationToken ct ,Int32 i)

39? ? ? ? {

40? ? ? ? ? ? Int32 sum = 0;

41? ? ? ? ? ? for (; i > 0; i--)

42? ? ? ? ? ? {

43? ? ? ? ? ? ? ? //在取消標志引用的CancellationTokenSource上如果調(diào)用

44? ? ? ? ? ? ? ? //Cancel垃喊,下面這一行就會拋出OperationCanceledException

45 46? ? ? ? ? ? ? ? ct.ThrowIfCancellationRequested();

47 48? ? ? ? ? ? ? ? checked { sum += i; }

49? ? ? ? ? ? }

50? ? ? ? ? ? 51? ? ? ? ? ? return sum;

52? ? ? ? }

53? ? }

  這個例子展示了一個任務在進行的時候中途取消的操作猾普,我覺得它很有趣,你試試也會發(fā)現(xiàn)本谜〕跫遥  Lamada表達式寫這個,是個亮點乌助,得學學溜在,將CancellationToken閉包變量“傳遞”。

 如果不用Lamada表達式他托,這問題還真不好解決:  Taskt = new Task(() => Sum(cts.Token,10000), cts.Token);  Sum(cts.Token,10000) 內(nèi)的Token需要和cts.Token關聯(lián)起來掖肋,你還能想出怎么關聯(lián)起來么?

  好上祈,任務取消也講玩了培遵,來看個更好用的技術:

1? ? ? ? static void Main(string[] args)?

2? ? ? ? {?

3? 4? ? ? ? ? ? Taskt = new Task(i => Sum((Int32)i),10000);?

5? 6? ? ? ? ? ? //可以現(xiàn)在開始,也可以以后開始??

7? ? ? ? ? ? ? 8? ? ? ? ? ? t.Start();?

9 10? ? ? ? ? ? Task cwt =? t.ContinueWith(task=>Console.WriteLine("The sum is:{0}",task.Result));

11? ? ? ? ? ? cwt.Wait();

12? ? ? ? ? ? 13? ? ? ? }

14 15? ? ? ? private static Int32 Sum(Int32 i)

16? ? ? ? {

17? ? ? ? ? ? Int32 sum = 0;

18? ? ? ? ? ? for (; i > 0; i--)

19? ? ? ? ? ? {

20? ? ? ? ? ? ? ? checked { sum += i; }

21? ? ? ? ? ? }

22? ? ? ? ? ? 23? ? ? ? ? ? return sum;

24? ? ? ? }

25? ? }

ContinueWith登刺?? 啥東西~~籽腕??  要寫可伸縮的軟件纸俭,一定不能使你的線程阻塞皇耗。這意味著如果調(diào)用Wait或者在任務未完成時查詢Result屬性,極有可能造成線程池創(chuàng)建一個新線程揍很,這增大了資源的消耗郎楼,并損害了伸縮性≈匣冢  ContinueWith便是一個更好的方式呜袁,一個任務完成時它可以啟動另一個任務。上面的例子不會阻塞任何線程简珠。

 當Sum的任務完成時阶界,這個任務會啟動另一個任務以顯示結果。ContinueWith會返回對新的Task對象的一個引用聋庵,所以為了看到結果膘融,我需要調(diào)用一下Wait方法,當然你也可以查詢下Result祭玉,或者繼續(xù)ContinueWith氧映,返回的這個對象可以忽略,它僅僅是一個變量脱货〉憾迹  還要指出的是律姨,Task對象內(nèi)部包含了ContinueWith任務的一個集合。所以臼疫,實際上可以用一個Task對象來多次調(diào)用ContinueWith线召。任務完成時,所有ContinueWith任務都會進入線程池隊列中多矮,在構造ContinueWith的時候我們可以看到一個TaskContinuationOptions枚舉值缓淹,不能忽視,看看它的定義:PrefereFairness是盡量公平的意思塔逃,就是較早調(diào)度的任務可能較早的運行讯壶,先來后到,將線程放到全局隊列湾盗,便可以實現(xiàn)這個效果伏蚊。ExecuteSynchronously指同步執(zhí)行,強制兩個任務用同一個線程一前一后運行格粪,然后就同步運行了躏吊。 看得是不是暈乎乎 ?有這么多枚舉例子帐萎,怎么掌握氨确?多看幾次疆导,知道任務的使用情況赁项,以后用起來得心應手~想學新技術,就要能耐住澈段,才能基礎牢固悠菜。來看個例子,用用這些枚舉败富。

?1? ? ? ? static void Main(string[] args)?

2? ? ? ? {?

3? ? ? ? ? ? Taskt = new Task(i => Sum((Int32)i),10000);?

4? 5? ? ? ? ? ? t.Start();?

6? 7? ? ? ? ? ? t.ContinueWith(task=>Console.WriteLine("The sum is:{0}",task.Result), 8? ? ? ? ? ? ? ? TaskContinuationOptions.OnlyOnRanToCompletion);?

9? ? ? ? ? ? 10? ? ? ? ? ? t.ContinueWith(task=>Console.WriteLine("Sum throw:"+task.Exception),11? ? ? ? ? ? ? ? TaskContinuationOptions.OnlyOnFaulted);

12? ? ? ? ? ? 13? ? ? ? ? ? t.ContinueWith(task=>Console.WriteLine("Sum was cancel:"+task.IsCanceled),14? ? ? ? ? ? ? ? TaskContinuationOptions.OnlyOnCanceled);

15? ? ? ? ? ? try

16? ? ? ? ? ? {

17? ? ? ? ? ? ? ? t.Wait();? // 測試用

18? ? ? ? ? ? }

19? ? ? ? ? ? catch (AggregateException)

20? ? ? ? ? ? {

21? ? ? ? ? ? ? ? Console.WriteLine("出錯");

22? ? ? ? ? ? }

23? ? ? ? ? ? 24? ? ? ? ? ? 25? ? ? ? }

26 27? ? ? ? private static Int32 Sum(Int32 i)

28? ? ? ? {

29? ? ? ? ? ? Int32 sum = 0;

30? ? ? ? ? ? for (; i > 0; i--)

31? ? ? ? ? ? {

32? ? ? ? ? ? ? ? checked { sum += i; }

33? ? ? ? ? ? }

34? ? ? ? ? ? 35? ? ? ? ? ? return sum;

36? ? ? ? }

37? ? }

  ContinueWith講完了悔醋。可是還沒有結束哦兽叮》医荆  AttachedToParnt枚舉類型(父任務)也不能放過!看看怎么用充择,寫法有點新奇德玫,看看:?

?1? ? ? ? static void Main(string[] args)?

2? ? ? ? {?

3? ? ? ? ? ? Taskparent = new Task(() => {

?4? ? ? ? ? ? ? ? var results = new Int32[3];?

5? ? ? ? ? ? ? ? //

?6? ? ? ? ? ? ? ? new Task(() => results[0] = Sum(10000), TaskCreationOptions.AttachedToParent).Start();?

7? ? ? ? ? ? ? ? new Task(() => results[1] = Sum(20000), TaskCreationOptions.AttachedToParent).Start();?

8? ? ? ? ? ? ? ? new Task(() => results[2] = Sum(30000), TaskCreationOptions.AttachedToParent).Start();?

9? ? ? ? ? ? ? ? return results;

10? ? ? ? ? ? });

11 12? ? ? ? ? ? var cwt = parent.ContinueWith( parentTask=>Array.ForEach(parentTask.Result,Console.WriteLine));

13? ? ? ? ? ? ? ? ? ? 14 15? ? ? ? ? ? parent.Start();

16? ? ? ? ? ? cwt.Wait();

17? ? ? ? }

18 19? ? ? ? private static Int32 Sum(Int32 i)

20? ? ? ? {

21? ? ? ? ? ? Int32 sum = 0;

22? ? ? ? ? ? for (; i > 0; i--)

23? ? ? ? ? ? {

24? ? ? ? ? ? ? ? checked { sum += i; }

25? ? ? ? ? ? }

26? ? ? ? ? ? return sum;

27? ? ? ? }

28? ? }復制代碼Oh匪蟀,我都寫暈了椎麦。。材彪。(+﹏+)~例子中观挎,父任務創(chuàng)建兵啟動3個Task對象琴儿。默認情況下,一個任務創(chuàng)建的Task對象是頂級任務嘁捷,這些任務跟創(chuàng)建它們的那個任務沒有關系造成。TaskCreationOptions.AttachedToParent標志將一個Task和創(chuàng)建它的那個Task關聯(lián)起來,除非所有子任務(子任務的子任務)結束運行雄嚣,否則創(chuàng)建任務(父任務)不會認為已經(jīng)結束晒屎。調(diào)用ContinueWith方法創(chuàng)建一個Task時,可以指定TaskContinuationOptions.AttachedToParent標志將延續(xù)任務置頂為一個子任務缓升。

 看了這么多任務的方法操作示例了鼓鲁,現(xiàn)在來挖挖任務內(nèi)部構造:  每個Task對象都有一組構成任務狀態(tài)的字段「垡辏  一個Int32 ID(只讀屬性)代表Task執(zhí)行狀態(tài)的一個Int32對父任務的一個引用對Task創(chuàng)建時置頂TaskSchedule的一個引用對回調(diào)方法的一個引用對要傳給回調(diào)方法的對象的一個引用(通過Task只讀AsyncState屬性查詢)對一個ExceptionContext的引用對一個ManualResetEventSlim對象的引用還有沒個Task對象都有對根據(jù)需要創(chuàng)建的一些補充狀態(tài)的一個引用骇吭,補充狀態(tài)包含這些:一個CancellationToken一個ContinueWithTask對象集合為拋出未處理異常的子任務,所準備的一個Task對象集合說了這么多歧寺,只想要大家知道:

雖然任務提供了大量功能燥狰,但并不是沒有代價的。因為必須為所有的這些狀態(tài)分配內(nèi)存斜筐。如果不需要任務提供的附加功能龙致,使用ThreadPool.QueueUserWorkItem,資源的使用效率會更高一些顷链。Task類還實現(xiàn)了IDispose接口净当,允許你在用完Task對象后調(diào)用Dispose,不過大多數(shù)不管蕴潦,讓垃圾回收器回收就好像啼。創(chuàng)建一個Task對象時,代表Task唯一的一個Int32字段初始化為零潭苞,TaskID從1開始忽冻,每分配一個ID都遞增1。順帶說一下此疹,在你調(diào)試中查看一個Task對象的時候僧诚,會造成調(diào)試器顯示Task的ID,從而造成為Task分配一個ID蝗碎『浚  這個ID的意義在于,每個Task都可以用一個唯一的值來標識蹦骑。Visual Studio會在它的“并行任務”和并行堆棿仁。“窗口中顯示這些任務ID。要知道的是眠菇,這是Visual Studio自己分配的ID边败,不是在自己代碼中分配的ID袱衷,幾乎不可能將Visual Studio分配的ID和代碼正在做的事情聯(lián)系起來。要查看自己正在運行的任務笑窜,可以在調(diào)試的時候查看Task的靜態(tài)CurrentId屬性致燥,如果沒有任務在執(zhí)行,CurrentId返回null排截∠釉椋  再看看TaskStatus的值,這個可以查詢Task對象的生存期:這些在任務運行的時候都是可以一一查到的断傲,還有~判斷要像這樣:1 if(task.Status==TaskStatus.RantoCompletion)...為了簡化編碼,Task只提供幾個只讀Boolean屬性:IsCanceled搬葬,IsFaulted,IsCompleted艳悔,它們能返回最終狀態(tài)true/false急凰。如果Task是通過調(diào)用某個函數(shù)來創(chuàng)建的,這個Task對象就會出于WaitingForActivation狀態(tài)猜年,它會自動運行抡锈。最后我們要來了解一下TaskFactory(任務工廠):

1.需要創(chuàng)建一組Task對象來共享相同的狀態(tài)

2.為了避免機械的將相同的參數(shù)傳給每一個Task的構造器。滿足這些條件就可以創(chuàng)建一個任務工廠來封裝通用的狀態(tài)乔外。TaskFactory類型和TaskFactory類型床三,它們都派生System.Object。你會學到不一樣的編碼方式:復制代碼 1? ? ? ? static void Main(string[] args) 2? ? ? ? {?

3? ? ? ? ? ? Task parent = new Task(() =>?

4? ? ? ? ? ? {?

5? ? ? ? ? ? ? ? var cts = new CancellationTokenSource();?

6? ? ? ? ? ? ? ? var tf = new TaskFactory(cts.Token, TaskCreationOptions.AttachedToParent, TaskContinuationOptions.ExecuteSynchronously, TaskScheduler.Default);

7

8? ? ? ? ? ? ? ? //創(chuàng)建并啟動3個子任務

9? ? ? ? ? ? ? ? var childTasks = new[] {

10? ? ? ? ? ? tf.StartNew(() => Sum(cts.Token, 10000)),

11? ? ? ? ? ? tf.StartNew(() => Sum(cts.Token, 20000)),

12? ? ? ? ? ? tf.StartNew(() => Sum(cts.Token, Int32.MaxValue))? // 這個會拋異常

13? ? ? ? ? };

14

15? ? ? ? ? ? ? ? // 任何子任務拋出異常就取消其余子任務

16? ? ? ? ? ? ? ? for (Int32 task = 0; task < childTasks.Length; task++)

17? ? ? ? ? ? ? ? ? ? childTasks[task].ContinueWith(t => cts.Cancel(), TaskContinuationOptions.OnlyOnFaulted);

18

19? ? ? ? ? ? ? ? // 所有子任務完成后杨幼,從未出錯/未取消的任務獲取返回的最大值

20? ? ? ? ? ? ? ? // 然后將最大值傳給另一個任務來顯示最大結果

21? ? ? ? ? ? ? ? tf.ContinueWhenAll(childTasks,

22? ? ? ? ? ? ? ? ? ? completedTasks => completedTasks.Where(t => !t.IsFaulted && !t.IsCanceled).Max(t => t.Result),

23? ? ? ? ? ? ? ? ? ? CancellationToken.None)

24? ? ? ? ? ? ? ? ? ? .ContinueWith(t => Console.WriteLine("The maxinum is: " + t.Result),

25? ? ? ? ? ? ? ? ? ? ? TaskContinuationOptions.ExecuteSynchronously).Wait(); // Wait用于測試

26? ? ? ? ? ? });

27

28? ? ? ? ? ? // 子任務完成后撇簿,也顯示任何未處理的異常

29? ? ? ? ? ? parent.ContinueWith(p =>

30? ? ? ? ? ? {

31? ? ? ? ? ? ? ? // 用StringBuilder輸出所有

32

33? ? ? ? ? ? ? ? StringBuilder sb = new StringBuilder("The following exception(s) occurred:" + Environment.NewLine);

34? ? ? ? ? ? ? ? foreach (var e in p.Exception.Flatten().InnerExceptions)

35? ? ? ? ? ? ? ? ? ? sb.AppendLine("? " + e.GetType().ToString());

36? ? ? ? ? ? ? ? Console.WriteLine(sb.ToString());

37? ? ? ? ? ? }, TaskContinuationOptions.OnlyOnFaulted);

38

39? ? ? ? ? ? // 啟動父任務

40? ? ? ? ? ? parent.Start();

41

42? ? ? ? ? ? try

43? ? ? ? ? ? {

44? ? ? ? ? ? ? ? parent.Wait(); //顯示結果

45? ? ? ? ? ? }

46? ? ? ? ? ? catch (AggregateException)

47? ? ? ? ? ? {

48? ? ? ? ? ? }

49? ? ? ? }

50

51? ? ? ? private static Int32 Sum(CancellationToken ct, Int32 n)

52? ? ? ? {

53? ? ? ? ? ? Int32 sum = 0;

54? ? ? ? ? ? for (; n > 0; n--)

55? ? ? ? ? ? {

56? ? ? ? ? ? ? ? ct.ThrowIfCancellationRequested();

57? ? ? ? ? ? ? ? checked { sum += n; }

58? ? ? ? ? ? }

59? ? ? ? ? ? return sum;

60? ? ? ? }

61? ? }

復制代碼

任務工廠就這么用,就是一個任務的集合差购。

現(xiàn)在看看TaskScheduler(任務調(diào)度)

任務基礎結構是很靈活的四瘫,TaskScheduler對象功不可沒。

TaskScheduler對象負責執(zhí)行調(diào)度的任務欲逃,同時向Visual Studio調(diào)試器公開任務信息找蜜,就像一座橋梁,讓我們能夠掌控自己的任務線程稳析。

TaskScheduler有兩個派生類:thread pool task scheduler(線程池任務調(diào)度)洗做,和synchronization context task scheduler(同步上下文任務調(diào)度器)。默認情況下彰居,所以應用程序使用的都是線程池任務調(diào)度器诚纸,這個任務調(diào)度器將任務調(diào)度給線程池的工作者線程〕露瑁可以查詢TaskScheduler的靜態(tài)Default屬性來獲得對默認任務調(diào)度器的一個引用畦徘。

同步上下文任務調(diào)度器通常用于桌面應用程序,Winfrom,WPF及Silverlight旧烧。這個任務調(diào)度器將多有任務都調(diào)度給應用程序的GUI線程,使所有任務代碼都能成功更新UI組建画髓,比如按鈕掘剪、菜單項等。同步上下文任務調(diào)度器根本不使用線程池奈虾。同樣夺谁,可以查詢TaskScheduler的靜態(tài)FromCurrentSynchronizationContext方法來獲得對一個同步上下文任務調(diào)度器的引用。

就像這樣創(chuàng)建類型:

1 //同步上下文任務調(diào)度

2 TaskScheduler m_syncContextTaskScheduler =

3? ? ? ? ? ? TaskScheduler.FromCurrentSynchronizationContext();

任務調(diào)度有很多的肉微,下面列舉一部分匾鸥,供參考,更多的請參看http://code.msdn.microsoft.com/ParExtSamples? 它包括了大量的示例代碼碉纳。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末勿负,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子劳曹,更是在濱河造成了極大的恐慌奴愉,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,544評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件铁孵,死亡現(xiàn)場離奇詭異锭硼,居然都是意外死亡,警方通過查閱死者的電腦和手機蜕劝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,430評論 3 392
  • 文/潘曉璐 我一進店門檀头,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人岖沛,你說我怎么就攤上這事暑始。” “怎么了婴削?”我有些...
    開封第一講書人閱讀 162,764評論 0 353
  • 文/不壞的土叔 我叫張陵蒋荚,是天一觀的道長。 經(jīng)常有香客問我馆蠕,道長期升,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,193評論 1 292
  • 正文 為了忘掉前任互躬,我火速辦了婚禮播赁,結果婚禮上,老公的妹妹穿的比我還像新娘吼渡。我一直安慰自己容为,他們只是感情好,可當我...
    茶點故事閱讀 67,216評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著坎背,像睡著了一般替劈。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上得滤,一...
    開封第一講書人閱讀 51,182評論 1 299
  • 那天陨献,我揣著相機與錄音,去河邊找鬼懂更。 笑死眨业,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的沮协。 我是一名探鬼主播龄捡,決...
    沈念sama閱讀 40,063評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼慷暂!你這毒婦竟也來了聘殖?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 38,917評論 0 274
  • 序言:老撾萬榮一對情侶失蹤行瑞,失蹤者是張志新(化名)和其女友劉穎就斤,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體蘑辑,經(jīng)...
    沈念sama閱讀 45,329評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡洋机,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,543評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了洋魂。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片绷旗。...
    茶點故事閱讀 39,722評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖副砍,靈堂內(nèi)的尸體忽然破棺而出衔肢,到底是詐尸還是另有隱情,我是刑警寧澤豁翎,帶...
    沈念sama閱讀 35,425評論 5 343
  • 正文 年R本政府宣布角骤,位于F島的核電站,受9級特大地震影響心剥,放射性物質(zhì)發(fā)生泄漏邦尊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,019評論 3 326
  • 文/蒙蒙 一优烧、第九天 我趴在偏房一處隱蔽的房頂上張望蝉揍。 院中可真熱鬧,春花似錦畦娄、人聲如沸又沾。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,671評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽杖刷。三九已至励饵,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間滑燃,已是汗流浹背役听。 一陣腳步聲響...
    開封第一講書人閱讀 32,825評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留不瓶,地道東北人禾嫉。 一個月前我還...
    沈念sama閱讀 47,729評論 2 368
  • 正文 我出身青樓灾杰,卻偏偏與公主長得像蚊丐,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子艳吠,可洞房花燭夜當晚...
    茶點故事閱讀 44,614評論 2 353

推薦閱讀更多精彩內(nèi)容

  • 線程是創(chuàng)建并發(fā)的底層工具麦备,因此具有一定的局限性。 沒有簡單的方法可以從聯(lián)合(Join)線程得到“返回值”昭娩。因此必須...
    大捕獵店閱讀 5,649評論 0 3
  • 1. Java基礎部分 基礎部分的順序:基本語法凛篙,類相關的語法,內(nèi)部類的語法栏渺,繼承相關的語法呛梆,異常的語法,線程的語...
    子非魚_t_閱讀 31,623評論 18 399
  • 1、你是找愛人霎终,還是找傭人 咖啡店靠窗的座位坐著一對年輕男女滞磺。男人襯衣長褲,文質(zhì)彬彬莱褒。女孩白T牛仔裙击困,清純可人,那...
    丁小米米米閱讀 803評論 6 20
  • 這部動畫片給四星好評广凸,很值得去電影院看阅茶。 首先,電影院的3D效果很不錯谅海。因為這部動畫片的絕大部分場景都是在海里目派,還...
    Jianapple閱讀 332評論 0 1
  • 學習劉潤老師管理課程,有感而發(fā)胁赢,一個企業(yè)生命和一個人生命仿佛相似企蹭,沒有基業(yè)長青的企業(yè)和沒有長生不老的人是一個道...
    iomega閱讀 229評論 0 1