任務Task系列之使用CancellationToken取消Task


  本文參考書籍《CLR via C#》

  Task的取消采用一種形如令牌(Token)的方式。首先先構建一個CancellationTokenSource實例,然后任務中執行的方法必須能接受一個CancellationToken類型的參數。

  假設我們有這樣一個方法:

private static Int32 NumValue(CancellationToken token, Int32 n)
        {
            Int32 sum = 0;
            for (int i = 0; i < n; i++)
            {
                token.ThrowIfCancellationRequested();
                checked
                {
                    sum += i;
                }
            }
            return sum;
        }

  上述代碼中的循環中調用CancellationTokenThrowIfCancellationRequested()方法定時檢查操作是否已經取消,這個方法與CancellationToken的IsCancellationRequested屬性作用一致,如果CancellationTokenSource已經取消,ThrowIfCancellationRequested()會拋出一個異常表示當前任務已經被取消。

  我們創建Task和CancellationTokenSource的對象:

 private static void TaskRun()
        {
            CancellationTokenSource tokenSource = new CancellationTokenSource();
            Task<Int32> task = Task.Run(() => NumValue(tokenSource.Token, 1000000), tokenSource.Token);

            //發出取消的請求
            tokenSource.Cancel();

            try
            {
                Console.WriteLine("計算求和為:{0}",task.Result);
            }
            catch (AggregateException ex)
            {
                ex.Handle(e => e is OperationCanceledException);
                Console.WriteLine("用戶已取消");
            }
        }

  可在創建Task時將一個CancellationToken傳給構造器,從而將兩者相關聯,如果CancellationToken在Task調度前取消,那么Task就會被取消,永遠都不執行。但如果Task已調度,那么Task的代碼就只支持顯示取消,其操作才能在執行期間取消,遺憾的是,雖然Task關聯了一個CancellationToken,但卻沒有辦法訪問他。因此,必須在Task的代碼中獲得創建Task對象時的同一個CancellationToken。為此,最簡單的辦法就是使用一個Lamda表達式,將CancellationToken作為閉包變量傳遞。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM