C# Task任務取消
阿新 • • 發佈:2022-04-10
需求:
在使用Blazor開發工具時,有個需求:
掃碼登入頁面需要不斷輪詢介面獲取掃碼狀態,並在對應的狀態下進行對應的操作:重新整理、登入、跳轉等;
此時,為了不阻塞前端的響應,需要我們開啟一個執行緒進行狀態檢測,並在完成後結束執行緒任務;
方案:
使用取消令牌(CancellationTokenSource);
相對操作比較簡單,需要結束時呼叫Cancel(),同時,在Task內部進行IsCancellationRequested狀態監聽、或者使用暴力呼叫ThrowIfCancellationRequested()(同樣需要不間斷的呼叫,Cancel後才可觸發,本質上也是校驗IsCancellationRequested狀態);
var cts = new CancellationTokenSource(); var tk = cts.Token; // 將CancellationToken傳入action中,然後對其取消狀態進行跟蹤 _ = Task.Factory.StartNew(async tk => { CancellationToken ct = (CancellationToken)tk; while (true) { ct.ThrowIfCancellationRequested(); Console.WriteLine("迴圈中" + Thread.CurrentThread.ManagedThreadId); await Task.Delay(1000); } }, tk, TaskCreationOptions.LongRunning); // OR // 此處是對於取消註冊個回撥方法,在取消後進行呼叫 _ = Task.Factory.StartNew(async tk => { var state = true; CancellationToken ct = (CancellationToken)tk; ct.Register(() => { state = false; }); while (state) { Console.WriteLine("迴圈中" + Thread.CurrentThread.ManagedThreadId); await Task.Delay(1000); } }, tk, TaskCreationOptions.LongRunning);
注意:
- 在使用Task.Run() 或 Task.Factory.StartNew()時,有個引數為傳入CancellationToken,如:Run(Action, CancellationToken);該cancellationToken不會傳遞到Task內,更不會對Task內不造成影響,該cancellationToken 只是用於取消Run() 或 StartNew();
- ck.Register可進行多次,構成連結串列執行,連結串列為倒敘的(最先註冊的最後執行);
擴充套件
CancellationTokenSource 具體實現原始碼解析:淺談C#取消令牌CancellationTokenSource
相關專案:WeComLoad Demo