第七节:利用CancellationTokenSource实现任务取消和利用CancellationToken类检测取消异常。
一. 傳統(tǒng)的線程取消
? 所謂的線程取消,就是線程正在執(zhí)行的過程中取消線程任務(wù)。
? 傳統(tǒng)的線程取消,是通過一個變量來控制,但是這種方式,在release模式下,被優(yōu)化從cpu高速緩存中讀取,而不是從內(nèi)存中讀取,會造成主線程無法執(zhí)行這一個bug。
1 {2 var isStop = false;3 var thread = new Thread(() =>4 {5 while (!isStop)6 {7 Thread.Sleep(100);8 Console.WriteLine("當(dāng)前thread={0} 正在運(yùn)行", Thread.CurrentThread.ManagedThreadId);9 } 10 }); 11 thread.Start(); 12 Thread.Sleep(1000); 13 isStop = true; 14 }?
PS:?通過上面的代碼看可以看出來,傳統(tǒng)模式的線程取消,在排除release模式bug的情況下,局限性還是很明顯的。比如:當(dāng)子線程任務(wù)取消的那一刻,我想執(zhí)行另外一項(xiàng)任務(wù);我想延時(shí)取消一個線程任務(wù);線程取消的時(shí)候拋異常。
上述這幾種情況,我們都要借助單獨(dú)的類來處理。
?
二.?CancellationTokenSource實(shí)現(xiàn)任務(wù)取消?
1.?取消任務(wù)的同時(shí)觸發(fā)一個函數(shù)
? 利用Cancel方法、Register注冊、source.Token標(biāo)記取消位來實(shí)現(xiàn)。
{CancellationTokenSource source = new CancellationTokenSource();//注冊一個線程取消后執(zhí)行的邏輯source.Token.Register(() =>{//這里執(zhí)行線程被取消后的業(yè)務(wù)邏輯.Console.WriteLine("-------------我是線程被取消后的業(yè)務(wù)邏輯---------------------");});Task.Run(() =>{while (!source.IsCancellationRequested){Thread.Sleep(100);Console.WriteLine("當(dāng)前thread={0} 正在運(yùn)行", Thread.CurrentThread.ManagedThreadId);}}, source.Token);Thread.Sleep(2000);source.Cancel();}2. 延時(shí)取消
線程的延時(shí)取消有兩種方式:
方案一:CancelAfter方法。
1 #region 方案一:CancelAfter方法2 {3 CancellationTokenSource source = new CancellationTokenSource();4 //注冊一個線程取消后執(zhí)行的邏輯5 source.Token.Register(() =>6 {7 //這里執(zhí)行線程被取消后的業(yè)務(wù)邏輯.8 Console.WriteLine("-------------我是線程被取消后的業(yè)務(wù)邏輯---------------------");9 }); 10 11 Task.Run(() => 12 { 13 while (!source.IsCancellationRequested) 14 { 15 Thread.Sleep(100); 16 Console.WriteLine("當(dāng)前thread={0} 正在運(yùn)行", Thread.CurrentThread.ManagedThreadId); 17 } 18 }, source.Token); 19 20 Thread.Sleep(2000); 21 //4s后自動取消 22 source.CancelAfter(new TimeSpan(0, 0, 0, 4)); 23 } 24 #endregion方案二:CancellationTokenSource構(gòu)造函數(shù)(不再需要Cancel方法了)。
1 {2 //4s后自動取消3 CancellationTokenSource source = new CancellationTokenSource(4000);4 //注冊一個線程取消后執(zhí)行的邏輯5 source.Token.Register(() =>6 {7 //這里執(zhí)行線程被取消后的業(yè)務(wù)邏輯.8 Console.WriteLine("-------------我是線程被取消后的業(yè)務(wù)邏輯---------------------");9 }); 10 11 Task.Run(() => 12 { 13 while (!source.IsCancellationRequested) 14 { 15 Thread.Sleep(100); 16 Console.WriteLine("當(dāng)前thread={0} 正在運(yùn)行", Thread.CurrentThread.ManagedThreadId); 17 } 18 }, source.Token); 19 20 Thread.Sleep(2000); 21 }?
3. 組合取消
?利用CreateLinkedTokenSource構(gòu)建CancellationTokenSource的組合體,其中任何一個體取消,則組合體就取消。?
{CancellationTokenSource source1 = new CancellationTokenSource();//source1.Cancel();CancellationTokenSource source2 = new CancellationTokenSource();source2.Cancel();var combineSource = CancellationTokenSource.CreateLinkedTokenSource(source1.Token, source2.Token);Console.WriteLine("s1={0} s2={1} s3={2}", source1.IsCancellationRequested,source2.IsCancellationRequested,combineSource.IsCancellationRequested);}上述代碼,source1和source2中的任何一個取消,combineSource就會被取消。
?
三.?CancellationToken類監(jiān)控取消
? CancellationToken類下ThrowIfCancellationRequested屬性,等價(jià)于if (XXX.IsCancellationRequested){throw new Exception("報(bào)錯了");}
? 只要取消就報(bào)錯。
1 {2 CancellationTokenSource source1 = new CancellationTokenSource();3 CancellationTokenSource source2 = new CancellationTokenSource();4 var combineSource = CancellationTokenSource.CreateLinkedTokenSource(source1.Token, source2.Token);5 source1.Cancel();6 7 //if (combineSource.IsCancellationRequested)8 //{9 // throw new Exception("報(bào)錯了"); 10 //} 11 12 //等價(jià)于上面那句話 13 try 14 { 15 combineSource.Token.ThrowIfCancellationRequested(); 16 } 17 catch (Exception) 18 { 19 Console.WriteLine("報(bào)錯了"); 20 } 21 22 23 Console.WriteLine("s1={0} s2={1} s3={2}", source1.IsCancellationRequested, 24 source2.IsCancellationRequested, 25 combineSource.IsCancellationRequested); 26 } 創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎總結(jié)
以上是生活随笔為你收集整理的第七节:利用CancellationTokenSource实现任务取消和利用CancellationToken类检测取消异常。的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 安卓之光 小米12 Ultra入网:年度
- 下一篇: 第十五节:深入理解async和await