1. 程式人生 > 其它 >C# Task任務取消

C# Task任務取消

需求:

在使用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