取消任務(Task)


 1         private static void TaskCancelDemo()
 2         {
 3             //向應該被取消的 System.Threading.CancellationToken 發送信號
 4             CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
 5 
 6             //將在線程池上運行的指定工作排隊,並返回代表該工作的 Task(TResult) 對象。 借助取消標記,可取消工作。
 7             //以異步方式執行的工作量。應用以取消工作的取消標記。
 8             Task<int> task = Task.Run(() => Sum(cancellationTokenSource.Token, 100000000), cancellationTokenSource.Token);
 9 
10             Thread.Sleep(10);
11             //Thread.Sleep(1);
12 
13             //傳達取消請求
14             //這是異步請求,Task可能未完成也可能已經完成
15             cancellationTokenSource.Cancel();
16 
17             try
18             {
19                 //若任務已取消,則Result會拋出AggregateException
20                 Console.WriteLine("Sum is " + task.Result);
21             }
22             catch (AggregateException aggregateException)
23             {
24                 //捕獲方式一
25                 //如果是OperationCanceledException,則返回true,表示已處理該異常
26                 //如果不是,則返回false,表示該異常未處理,會拋出一個新的AggregateException
27                 //aggregateException.Handle(handle => handle is OperationCanceledException);
28 
29                 //捕獲方式二
30                 //首先設置永遠返回true,表示所有異常已處理,不再新拋出
31                 aggregateException.Handle(handle =>
32                 {
33                     //將任何OperationCanceledException對象都視為已處理(打印輸出)
34                     if (handle is OperationCanceledException)
35                     {
36                         Console.WriteLine("Sum was cancelled.");
37                     }
38                     else//如果不是OperationCanceledException,則也已處理(打印輸出)
39                     {
40                         Console.WriteLine(aggregateException.Message);
41                         foreach (var e in aggregateException.InnerExceptions)
42                         {
43                             Console.WriteLine(e.Message);
44                         }
45                     }
46 
47                     //注:若返回false,則其它(OperationCanceledException除外,因為上面已經處理過)
48                     //任何異常都造成拋出一個新的AggregateException
49                     //若返回true,則已處理異常,不再拋出(即使包含未處理的異常)
50                     return true;
51                 });
52 
53                 //所有異常都處理完成后,執行下面的代碼
54                 Console.WriteLine("All exceptions are handled.");
55             }
56         }
57 
58         /// <summary>
59         /// n以內正整數求和
60         /// </summary>
61         /// <param name="cancellationToken">取消操作的通知</param>
62         /// <param name="n"></param>
63         /// <returns></returns>
64         private static int Sum(CancellationToken cancellationToken, int n)
65         {
66             int sum = 0;
67             for (; n > 0; n--)
68             {
69                 //在取消標識引用的CancellationTokenSource上調用Cancel
70                 //如果已請求取消此標記,則引發 System.OperationCanceledException
71                 cancellationToken.ThrowIfCancellationRequested();
72 
73                 //檢查n值,若太大,則拋出OverflowException
74                 checked { sum = sum + n; }
75             }
76             return sum;
77         }

    在創建Task時將一個CancellationToken傳給構造器(如上例所示),從而將兩者關聯。但是,雖然Task對象關聯了一個CancellationToken,但卻沒有辦法訪問它。因此,必須在Task的代碼中獲得創建Task對象時的同一個CancellationToken。為此,最簡單的辦法就是使用一個lambda表達式,將CancellationToken作為閉包變量“傳遞”(如上例所示)。如果CancellationToken在Task調度前取消(會拋出InvalidOperationException),Task會被取消,永遠都不執行。但如果Task已調度(通過Start,或者Run,靜態Run方法會自動創建Task對象並立即調用Start),那么Task的代碼只有顯式支持取消,其操作才能在執行期間取消。

 


免責聲明!

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



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