System.Threading.Tasks.Task 和 System.Threading.Tasks.Task<TResult> 類別透過取消標記來支援取消。 如需詳細資訊,請參閱 管理線程中的取消操作。 在 Task 類別中,取消涉及用戶委派與請求取消的程式碼之間的合作,其中用戶委派代表可取消的操作。 成功的取消涉及要求程式碼呼叫CancellationTokenSource.Cancel方法,並且使用者委派會及時終止操作。 您可以使用下列其中一個選項來終止作業:
從委派的任務返回。 在許多情況下,此選項就已足夠。 不過,以這種方式取消的工作實例會轉換到TaskStatus.RanToCompletion狀態,而不是TaskStatus.Canceled狀態。
藉由拋出一個 OperationCanceledException 並傳遞用來請求取消的令牌。 執行方式的慣用方式是使用 ThrowIfCancellationRequested 方法。 以這種方式取消的工作會轉換為已取消狀態,呼叫端程式代碼可用來驗證工作回應其取消要求。
下列範例顯示引發例外狀況的工作取消基本模式:
備註
令牌會傳遞給使用者委派和工作實例。
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
var tokenSource2 = new CancellationTokenSource();
CancellationToken ct = tokenSource2.Token;
var task = Task.Run(() =>
{
// Were we already canceled?
ct.ThrowIfCancellationRequested();
bool moreToDo = true;
while (moreToDo)
{
// Poll on this property if you have to do
// other cleanup before throwing.
if (ct.IsCancellationRequested)
{
// Clean up here, then...
ct.ThrowIfCancellationRequested();
}
}
}, tokenSource2.Token); // Pass same token to Task.Run.
tokenSource2.Cancel();
// Just continue on this thread, or await with try-catch:
try
{
await task;
}
catch (OperationCanceledException e)
{
Console.WriteLine($"{nameof(OperationCanceledException)} thrown with message: {e.Message}");
}
finally
{
tokenSource2.Dispose();
}
Console.ReadKey();
}
}
Imports System.Threading
Imports System.Threading.Tasks
Module Test
Sub Main()
Dim tokenSource2 As New CancellationTokenSource()
Dim ct As CancellationToken = tokenSource2.Token
Dim t2 = Task.Factory.StartNew(Sub()
' Were we already canceled?
ct.ThrowIfCancellationRequested()
Dim moreToDo As Boolean = True
While moreToDo = True
' Poll on this property if you have to do
' other cleanup before throwing.
If ct.IsCancellationRequested Then
' Clean up here, then...
ct.ThrowIfCancellationRequested()
End If
End While
End Sub _
, tokenSource2.Token) ' Pass same token to StartNew.
' Cancel the task.
tokenSource2.Cancel()
' Just continue on this thread, or Wait/WaitAll with try-catch:
Try
t2.Wait()
Catch e As AggregateException
For Each item In e.InnerExceptions
Console.WriteLine(e.Message & " " & item.Message)
Next
Finally
tokenSource2.Dispose()
End Try
Console.ReadKey()
End Sub
End Module
如需完整的範例,請參閱 如何:取消任務及其子任務。
當任務實例觀察到使用者程式碼擲出OperationCanceledException時,它會比較該例外狀況的令牌與其相關聯的令牌(傳遞至 API 以建立任務)。 如果令牌相同且令牌的 IsCancellationRequested 屬性傳回 true
,該工作會將此解譯為認可取消,並轉換為已取消狀態。 如果您不使用 Wait 或 WaitAll 方法來等候工作,則工作只會將其狀態設定為 Canceled。
如果您正在等候一個轉換至已取消狀態的工作,則會拋出一個例外狀況(此例外狀況被包裝在例外狀況 System.Threading.Tasks.TaskCanceledException 中)。 此例外狀況表示取消成功,而不是發生錯誤的情況。 因此,工作的 Exception 屬性會傳回 null
。
如果令牌的 IsCancellationRequested 屬性返回 false
,或者例外狀況的令牌不符合 Task 的令牌,則 OperationCanceledException 會被視為一般例外狀況,導致 Task 轉換為出錯狀態。 其他例外狀況的存在也會導致工作轉換為錯誤狀態。 您可以在 屬性中 Status 取得已完成工作的狀態。
在要求取消之後,工作可能會繼續處理某些項目。