取消工作
System.Threading.Tasks.Task 和 System.Threading.Tasks.Task<TResult> 類別會使用取消語彙基元支援取消。 如需詳細資訊,請參閱受控執行緒中的取消作業。 在 Task 類別中,取消作業包括使用者委派之間的合作,這是指可取消的作業和要求取消的程式碼。 成功的取消作業包括要求呼叫 CancellationTokenSource.Cancel 方法的程式碼,以及適時終止作業的使用者委派。 您可以使用下列選項之一來終止作業:
藉由從委派傳回。 在許多情況下,此選項就已足夠。 不過,以這種方式取消的工作執行個體將會轉換至 TaskStatus.RanToCompletion 狀態,而非 TaskStatus.Canceled 狀態。
透過擲回 OperationCanceledException,並將其傳遞至據以要求取消的語彙基元。 執行此作業的常見方式是使用 ThrowIfCancellationRequested 方法。 以此方式取消的工作會轉換至 Canceled 狀態,可供呼叫端節點用以驗證工作已回應其取消要求。
下列範例說明會擲回例外狀況的工作取消基本模式:
注意
語彙基元不但會傳遞至使用者委派,也會傳遞至工作執行個體。
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
,則工作會將此解譯成確認取消,並轉換至 Canceled 狀態。 如果未使用 Wait 或 WaitAll 方法等候工作,則工作只會將其狀態設為 Canceled。
如果您正在等候轉換至 Canceled 狀態的工作,則會擲回 System.Threading.Tasks.TaskCanceledException 例外狀況 (包裝在 AggregateException 例外狀況中)。 請注意,此例外狀況表示取消成功,而非錯誤情況。 因此,工作的 Exception 屬性會傳回 null
。
如果語彙基元的 IsCancellationRequested 屬性傳回 false
,或例外狀況的語彙基元不符合工作的語彙基元,則 OperationCanceledException 會被視為一般例外狀況,而使工作轉換至 Faulted 狀態。 如有其他例外狀況存在,也會使工作轉換至 Faulted 狀態。 您可以在 Status 屬性中取得已完成工作的狀態。
在要求取消之後,工作仍有可能會繼續處理某些項目。