第六节:深入研究Task实例方法ContinueWith的参数TaskContinuationOptions
一. 整體說明
揭秘:
該章節(jié)的性質(zhì)和上一個(gè)章節(jié)類似,也是一個(gè)擴(kuò)展的章節(jié),主要來研究Task類下的實(shí)例方法ContinueWith中的參數(shù)TaskContinuationOptions。
通過F12查看TaskContinuationOptions的源碼,知道主要有這么幾個(gè)參數(shù):
①. LazyCancellation:在延續(xù)取消的情況下,防止延續(xù)的完成直到完成先前的任務(wù)。
(下面的例子task2取消,原先的延續(xù)關(guān)系不復(fù)存在,task1和task3可以并行執(zhí)行)
②. ExecuteSynchronously:希望執(zhí)行前面那個(gè)task的thread也在執(zhí)行本延續(xù)任務(wù)
(下面的例子執(zhí)行task2的Thread和執(zhí)行task1的Thread是同一個(gè),所有二者的線程id相同)
③. NotOnRanToCompletion和OnlyOnRanToCompletion
NotOnRanToCompletion:延續(xù)任務(wù)必須在前面task非完成狀態(tài)才能執(zhí)行
OnlyOnRanToCompletion:延續(xù)任務(wù)必須在前面task完成狀態(tài)才能執(zhí)行
(下面例子:注釋掉異常的這句代碼task2不能執(zhí)行,task3能執(zhí)行;不注釋,task2能執(zhí)行,task3不能執(zhí)行)
?源碼如下:
1 [Serializable]2 [Flags]3 public enum TaskContinuationOptions4 {5 // 摘要: 6 // Default = "Continue on any, no task options, run asynchronously" 指定應(yīng)使用默認(rèn)行為。7 // 默認(rèn)情況下,完成前面的任務(wù)之后將安排運(yùn)行延續(xù)任務(wù),而不考慮前面任務(wù)的最終 System.Threading.Tasks.TaskStatus。8 None = 0,9 // 10 // 摘要: 11 // 提示 System.Threading.Tasks.TaskScheduler 以一種盡可能公平的方式安排任務(wù),這意味著較早安排的任務(wù)將更可能較早運(yùn)行,而較晚安排運(yùn)行的任務(wù)將更可能較晚運(yùn)行。 12 PreferFairness = 1, 13 // 14 // 摘要: 15 // 指定某個(gè)任務(wù)將是運(yùn)行時(shí)間長(zhǎng)、粗粒度的操作。 它會(huì)向 System.Threading.Tasks.TaskScheduler 提示,過度訂閱可能是合理的。 16 LongRunning = 2, 17 // 18 // 摘要: 19 // 指定將任務(wù)附加到任務(wù)層次結(jié)構(gòu)中的某個(gè)父級(jí)。 20 AttachedToParent = 4, 21 // 22 // 摘要: 23 // 如果嘗試附有子任務(wù)到創(chuàng)建的任務(wù),指定 System.InvalidOperationException 將被引發(fā)。 24 DenyChildAttach = 8, 25 // 26 // 摘要: 27 // 防止環(huán)境計(jì)劃程序被視為已創(chuàng)建任務(wù)的當(dāng)前計(jì)劃程序。 這意味著像 StartNew 或 ContinueWith 創(chuàng)建任務(wù)的執(zhí)行操作將被視為 System.Threading.Tasks.TaskScheduler.Default 28 // 當(dāng)前計(jì)劃程序。 29 HideScheduler = 16, 30 // 31 // 摘要: 32 // 在延續(xù)取消的情況下,防止延續(xù)的完成直到完成先前的任務(wù)。 33 LazyCancellation = 32, 34 // 35 // 摘要: 36 // 指定不應(yīng)在延續(xù)任務(wù)前面的任務(wù)已完成運(yùn)行的情況下安排延續(xù)任務(wù)。 此選項(xiàng)對(duì)多任務(wù)延續(xù)無效。 37 NotOnRanToCompletion = 65536, 38 // 39 // 摘要: 40 // 指定不應(yīng)在延續(xù)任務(wù)前面的任務(wù)引發(fā)了未處理異常的情況下安排延續(xù)任務(wù)。 此選項(xiàng)對(duì)多任務(wù)延續(xù)無效。 41 NotOnFaulted = 131072, 42 // 43 // 摘要: 44 // 指定只應(yīng)在延續(xù)任務(wù)前面的任務(wù)已取消的情況下才安排延續(xù)任務(wù)。 此選項(xiàng)對(duì)多任務(wù)延續(xù)無效。 45 OnlyOnCanceled = 196608, 46 // 47 // 摘要: 48 // 指定不應(yīng)在延續(xù)任務(wù)前面的任務(wù)已取消的情況下安排延續(xù)任務(wù)。 此選項(xiàng)對(duì)多任務(wù)延續(xù)無效。 49 NotOnCanceled = 262144, 50 // 51 // 摘要: 52 // 指定只應(yīng)在延續(xù)任務(wù)前面的任務(wù)引發(fā)了未處理異常的情況下才安排延續(xù)任務(wù)。 此選項(xiàng)對(duì)多任務(wù)延續(xù)無效。 53 OnlyOnFaulted = 327680, 54 // 55 // 摘要: 56 // 指定只應(yīng)在延續(xù)任務(wù)前面的任務(wù)已完成運(yùn)行的情況下才安排延續(xù)任務(wù)。 此選項(xiàng)對(duì)多任務(wù)延續(xù)無效。 57 OnlyOnRanToCompletion = 393216, 58 // 59 // 摘要: 60 // 指定應(yīng)同步執(zhí)行延續(xù)任務(wù)。 指定此選項(xiàng)后,延續(xù)任務(wù)將在導(dǎo)致前面的任務(wù)轉(zhuǎn)換為其最終狀態(tài)的相同線程上運(yùn)行。 如果在創(chuàng)建延續(xù)任務(wù)時(shí)已經(jīng)完成前面的任務(wù),則延續(xù)任務(wù)將在創(chuàng)建此延續(xù)任務(wù)的線程上運(yùn)行。 61 // 只應(yīng)同步執(zhí)行運(yùn)行時(shí)間非常短的延續(xù)任務(wù)。 62 ExecuteSynchronously = 524288, 63 }?
二. 實(shí)際測(cè)試
? 下面通過代碼來說明默認(rèn)情況下、LazyCancellation、ExecuteSynchronously、NotOnRanToCompletion和OnlyOnRanToCompletion的作用和效果。
1. 默認(rèn)情況
? 默認(rèn)情況下,task1執(zhí)行完后→task2→task2執(zhí)行完后→task3。
1 {2 Task task1 = new Task(() =>3 {4 Thread.Sleep(1000);5 Console.WriteLine("task1 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);6 });7 8 var task2 = task1.ContinueWith(t =>9 { 10 Console.WriteLine("task2 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now); 11 }); 12 13 var task3 = task2.ContinueWith(t => 14 { 15 Console.WriteLine("task3 tid={0}, dt={1} {2}", Thread.CurrentThread.ManagedThreadId, DateTime.Now, task2.Status); 16 }); 17 18 task1.Start(); 19 20 }?運(yùn)行結(jié)果: task1執(zhí)行完后→ task2執(zhí)行→task2執(zhí)行完后→ task3執(zhí)行。
2. LazyCancellation
? 作用:取消該線程,該線程的前一個(gè)線程和后一個(gè)線程并行執(zhí)行。
1 {2 CancellationTokenSource source = new CancellationTokenSource();3 source.Cancel();4 5 Task task1 = new Task(() =>6 {7 Thread.Sleep(1000);8 Console.WriteLine("task1 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);9 }); 10 11 var task2 = task1.ContinueWith(t => 12 { 13 Console.WriteLine("task2 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now); 14 }, source.Token, TaskContinuationOptions.LazyCancellation, TaskScheduler.Current); 15 16 var task3 = task2.ContinueWith(t => 17 { 18 Console.WriteLine("task3 tid={0}, dt={1} {2}", Thread.CurrentThread.ManagedThreadId, DateTime.Now, task2.Status); 19 }); 20 21 task1.Start(); 22 23 }??運(yùn)行結(jié)果: task2線程已經(jīng)被取消,task1線程和task2線程并行執(zhí)行。
3.?ExecuteSynchronously
? 作用:希望執(zhí)行前面那個(gè)task的thread也在執(zhí)行本延續(xù)任務(wù)。
1 {2 Task task1 = new Task(() =>3 {4 Thread.Sleep(1000);5 Console.WriteLine("task1 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);6 });7 8 var task2 = task1.ContinueWith(t =>9 { 10 Console.WriteLine("task2 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now); 11 }, TaskContinuationOptions.ExecuteSynchronously); 12 13 task1.Start(); 14 }? 結(jié)果:task1和task2線程的線程id相同。
4.?NotOnRanToCompletion和OnlyOnRanToCompletion
NotOnRanToCompletion:延續(xù)任務(wù)必須在前面task非完成狀態(tài)才能執(zhí)行。
OnlyOnRanToCompletion:延續(xù)任務(wù)必須在前面task完成狀態(tài)才能執(zhí)行。
{Task task1 = new Task(() =>{Thread.Sleep(1000);Console.WriteLine("task1 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);//手動(dòng)制造異常,表示不能執(zhí)行完畢//(注釋掉這句話task2不能執(zhí)行,task3能執(zhí)行)//不注釋,task2能執(zhí)行,task3不能執(zhí)行//throw new Exception("hello world");});var task2 = task1.ContinueWith(t =>{Console.WriteLine("task2 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);}, TaskContinuationOptions.NotOnRanToCompletion);var task3 = task1.ContinueWith(t =>{Console.WriteLine("task3 tid={0}, dt={1}", Thread.CurrentThread.ManagedThreadId, DateTime.Now);}, TaskContinuationOptions.OnlyOnRanToCompletion);task1.Start(); }分析:task2和task3均為task的延續(xù)線程,當(dāng)task1報(bào)錯(cuò)時(shí)候,task2執(zhí)行,task3不能執(zhí)行;當(dāng)task1正常時(shí)候,task2不能執(zhí)行,task3能執(zhí)行。
task1報(bào)錯(cuò)時(shí)的運(yùn)行結(jié)果:
task2正常時(shí)的運(yùn)行結(jié)果:
?
?
總結(jié)
以上是生活随笔為你收集整理的第六节:深入研究Task实例方法ContinueWith的参数TaskContinuationOptions的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 广发极客卡怎么申请 广发极客卡申请条件
- 下一篇: ABP入门系列(1)——通过模板创建MA