語言

任務取消

System.Threading.Tasks.Task 和 System.Threading.Tasks.Task<TResult> 類別透過取消標記來支援取消。 如需詳細資訊,請參閱 管理線程中的取消操作。 在 Task 類別中,取消涉及用戶委派與請求取消的程式碼之間的合作,其中用戶委派代表可取消的操作。 成功的取消涉及要求程式碼呼叫CancellationTokenSource.Cancel方法,並且使用者委派會及時終止操作。 您可以使用下列其中一個選項來終止作業:

下列範例顯示引發例外狀況的工作取消基本模式:

備註

令牌會傳遞給使用者委派和工作實例。

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 取得已完成工作的狀態。

在要求取消之後,工作可能會繼續處理某些項目。

另請參閱