asp.net core中,使用CancellationToken在用戶終止請求時取消全部異步操做+ abp中的設計

若是一個Controller.Action裏的處理很是耗時,好比讀數據庫、文件操做、調用第三方接口等
此時用戶隨時可能關閉瀏覽器、F5刷新網頁等操做。
可是服務端的耗時代碼任然在執行,這太浪費了,既然用戶終止請求了,咱們就應該取消全部的耗時操做git

在.net開發中,幾乎全部的異步方法都有個CancellationToken類型的參數,只要咱們傳入此令牌,未來咱們隨時能夠經過此令牌取消異步操做
而asp.net中HttpContext提供了一個RequestAborted屬性,它就是CancellationToken類型,當用戶以任何方式終止請求時, HttpContext.RequestAborted就會觸發取消
因此若是咱們在異步方法中都傳入這個參數,就能實現當用戶終止請求時,咱們全部的異步操做都會當即取消github

併發大的狀況下,這個操做很重要。數據庫

參考代碼:瀏覽器

1 public async Task<ActionResult> TestAsync()
2 {
3         await System.IO.File.ReadAllTextAsync(@"d:\a.txt", HttpContext.RequestAborted);
4         //....略        

 

上面是asp.net默認行爲,你會發現一個問題,真個應用程序有鋪天蓋地的異步方法,若是都想實現上述特徵 咱們全部的異步方法都得加上CancellationToken參數
abp提供了一種牛X的方式
它提供一個ICancellationTokenProvider接口,它會爲咱們提供一個CancellationToken對象,因此咱們定義的異步方法不須要定義CancellationToken參數了,首先在咱們的類中依賴注入這個接口,而後在調用.net內置庫或第三方庫的異步方法時,傳入ICancellationTokenProvider.Token就能夠了,以下:併發

1 ICancellationTokenProvider CancellationTokenProvider ;
2 
3 //構造函數注入CancellationTokenProvider 略...
4 
5 public override async Task<List<TEntity>> GetAllListAsync()
6 {
7             return await GetAll().ToListAsync(CancellationTokenProvider.Token);
8 }

比較推薦的是使用「空模式」,用屬性注入,以下:asp.net

1 public ICancellationTokenProvider CancellationToken { get; set; } = NullCancellationTokenProvider.Instance;

abp中最終使用的是HttpContextCancellationTokenProvider,它的Token屬性返回的就是HttpContext.RequestAborted異步


默認狀況下abp的Repository中的全部異步方法已經使用這種模式,因爲咱們開發是大部分狀況下都是數據庫讀寫,因此咱們在abp中幾乎能夠不關心這事,默認就是以合理的方式運行的。
但有時候咱們須要作其它異步操做,好比調用第三方接口啥的,此時就須要經過上面的方式來實現這種 用戶取消請求則因此異步操做理解取消的效果。async

在某些場景中咱們可能並不想用這種默認的行爲,而是但願傳入本身的CancellationToken對象,而不是用HttpContext的。這是我估計ICancellationTokenProvider.Use就派上用場了。怎麼用呢?ide

相關文章
相關標籤/搜索