Anulowanie zadaniaTask Cancellation

Klasy System.Threading.Tasks.Task i System.Threading.Tasks.Task<TResult> obsługują anulowanie przy użyciu tokenów anulowania w .NET Framework.The System.Threading.Tasks.Task and System.Threading.Tasks.Task<TResult> classes support cancellation through the use of cancellation tokens in the .NET Framework. Aby uzyskać więcej informacji, zobacz Anulowanie w zarządzanych wątkach.For more information, see Cancellation in Managed Threads. W klasach Task anulowanie pociąga za sobą współpracę pełnomocnika użytkownika, który reprezentuje możliwości anulowania operacji i kodu, który zażądał anulowania.In the Task classes, cancellation involves cooperation between the user delegate, which represents a cancelable operation and the code that requested the cancellation. Pomyślne anulowanie obejmuje żądanie kodu wywołującego metodę CancellationTokenSource.Cancel i delegata użytkownika kończącego operację w odpowiednim czasie.A successful cancellation involves the requesting code calling the CancellationTokenSource.Cancel method, and the user delegate terminating the operation in a timely manner. Można zakończyć operację przy użyciu jednej z następujących opcji:You can terminate the operation by using one of these options:

  • Powracając po prostu od pełnomocnika.By simply returning from the delegate. W wielu scenariuszach jest to wystarczające. Jednak wystąpienie zadania, które zostało anulowane w ten sposób, przechodzi do stanu TaskStatus.RanToCompletion, a nie do stanu TaskStatus.Canceled.In many scenarios this is sufficient; however, a task instance that is canceled in this way transitions to the TaskStatus.RanToCompletion state, not to the TaskStatus.Canceled state.

  • Przez wyrzucanie OperationCanceledException i przekazywanie go tokenem, na którym zażądano anulowania.By throwing a OperationCanceledException and passing it the token on which cancellation was requested. Preferowanym sposobem wykonania tej czynności jest użycie metody ThrowIfCancellationRequested.The preferred way to do this is to use the ThrowIfCancellationRequested method. Zadanie, które zostało anulowane w ten sposób, przechodzi do stanu Canceled, którego kod wywołujący może użyć do sprawdzenia, czy zadanie odpowiedziało na żądanie anulowania.A task that is canceled in this way transitions to the Canceled state, which the calling code can use to verify that the task responded to its cancellation request.

Poniższy przykład przedstawia podstawowy wzorzec anulowania zadania ze zgłoszeniem wyjątku.The following example shows the basic pattern for task cancellation that throws the exception. Należy zauważyć, że token jest przekazywany do pełnomocnika użytkownika i do samego wystąpienia zadania.Note that the token is passed to the user delegate and to the task instance itself.

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

Aby zapoznać się z bardziej kompletnym przykładem, zobacz How to: Anulowanie zadania i jego elementów podrzędnych.For a more complete example, see How to: Cancel a Task and Its Children.

Gdy wystąpienie zadania obserwuje OperationCanceledException zgłoszone przez kod użytkownika, porównuje token wyjątku ze skojarzonym tokenem (ten, który został przesłany do interfejsu API, który utworzył zadanie).When a task instance observes an OperationCanceledException thrown by user code, it compares the exception's token to its associated token (the one that was passed to the API that created the Task). Jeśli są takie same, a właściwość IsCancellationRequested tokenu zwraca wartość true, zadanie interpretuje je jako potwierdzenie anulowania i przejścia do stanu anulowane.If they are the same and the token's IsCancellationRequested property returns true, the task interprets this as acknowledging cancellation and transitions to the Canceled state. Jeśli nie używasz metody Wait lub WaitAll do oczekiwania na zadanie, zadanie po prostu ustawi jego stan na Canceled.If you do not use a Wait or WaitAll method to wait for the task, then the task just sets its status to Canceled.

Jeśli oczekujesz na zadanie, które przechodzi do stanu anulowanego, zostanie zgłoszony wyjątek System.Threading.Tasks.TaskCanceledException (opakowany w wyjątek AggregateException).If you are waiting on a Task that transitions to the Canceled state, a System.Threading.Tasks.TaskCanceledException exception (wrapped in an AggregateException exception) is thrown. Należy zauważyć, że ten wyjątek wskazuje pomyślne anulowanie, a nie błędną sytuację.Note that this exception indicates successful cancellation instead of a faulty situation. W związku z tym, właściwość Exception zadania zwraca null.Therefore, the task's Exception property returns null.

Jeśli właściwość IsCancellationRequested tokenu zwraca wartość false lub jeśli token wyjątku nie jest zgodny z tokenem zadania, OperationCanceledException jest traktowany jak normalny wyjątek, powodując przejście zadania do stanu błędu.If the token's IsCancellationRequested property returns false or if the exception's token does not match the Task's token, the OperationCanceledException is treated like a normal exception, causing the Task to transition to the Faulted state. Należy także zauważyć, że obecność innych wyjątków także spowoduje przejście zadania do stanu Faulted.Also note that the presence of other exceptions will also cause the Task to transition to the Faulted state. Stan ukończonego zadania można uzyskać we właściwości Status.You can get the status of the completed task in the Status property.

Możliwe jest, że zadanie będzie kontynuować przetwarzanie niektórych elementy po żądania anulowania.It is possible that a task may continue to process some items after cancellation is requested.

Zobacz takżeSee also