天天看點

【異步程式設計】Part3:取消異步操作

在.Net和C#中運作異步代碼相當簡單,因為我們有時候需要取消正在進行的異步操作,通過本文,可以掌握 通過CancellationToken取消任務(包括non-cancellable任務)。

Task 表示無傳回值的異步操作, 泛型版本Task<TResult>表示有傳回值的異步操作, 現在async/await 文法糖大大簡化了我們編寫異步程式的難度。

建立一個長時間運作的操作:

【異步程式設計】Part3:取消異步操作
【異步程式設計】Part3:取消異步操作

View Code

 簡單異步調用代碼:

因為一些原因我們會取消異步操作:

操作耗時較長,堵塞了其他正常請求;

不願意再等待執行結果了,手動取消

【異步程式設計】Part3:取消異步操作

其中關注

類CancellationTokenSource:給CancellationToken發出取消通知

結構體CancellationToken: 取消操作的通知。

CancellationToken結構體相當于打入在異步操作内部的楔子,随時等候CancellationTokenSource  發出的取消通知。

【異步程式設計】Part3:取消異步操作
【異步程式設計】Part3:取消異步操作

 定義異步方法時候設定 CancelletionToken參數

那麼這個異步方法即是Cancellable 的異步方法

在長時間運作的操作中監測 IsCancellationRequested方法 (目前是否發生取消指令),這裡我傾向去包裝一個TaskCanceledException異常類(給上層方法調用者更多處理的可能性); 當然可以調用ThrowIfCancellationRequested方法抛出OperationCanceledException異常。

【異步程式設計】Part3:取消異步操作

 發送取消通知

操縱以上CancellationToken狀态的對象是 CancellationTokenSource,這個對象是取消操作的指令釋出者。

手動取消操作

有時候,部分第三方異步操作代碼并不是可取消的,也就是以上長時間運作的異步操作LongRunningCancellableOperation(int loop, CancellationToken cancellationToken) 并不支援CancellationToken ,相當于不允許打入楔子。

這時我們怎樣取消 這樣的non-Cancellable 任務?

可考慮利用 Task.WhenAny( params tasks) 操作曲線取消:

利用TaskCompletionSource 注冊異步可取消任務

等待待non-cancellable 操作和以上建立的 異步取消操作

像上面代碼一樣執行取消指令 :

【異步程式設計】Part3:取消異步操作

大多數情況下,我們不需要編寫自定義可取消任務,因為我們隻需要使用現有API。但要知道它是如何在幕後工作總是好的。

+ https://johnthiriet.com/cancel-asynchronous-operation-in-csharp/

+ https://stackoverflow.com/questions/4238345/asynchronously-wait-for-taskt-to-complete-with-timeout

+ https://github.com/App-vNext/Polly/wiki/Timeout

本文來自部落格園,作者:{有态度的馬甲},轉載請注明原文連結:https://www.cnblogs.com/JulianHuang/p/10572840.html

歡迎關注我的原創技術、職場公衆号, 加好友談天說地,一起進化

【異步程式設計】Part3:取消異步操作

繼續閱讀