Cancelamento de tarefaTask cancellation

As System.Threading.Tasks.Task System.Threading.Tasks.Task<TResult> classes e dão suporte ao cancelamento por meio do uso de tokens de cancelamento.The System.Threading.Tasks.Task and System.Threading.Tasks.Task<TResult> classes support cancellation through the use of cancellation tokens. Para obter mais informações, consulte cancelamento em threads gerenciados.For more information, see Cancellation in Managed Threads. Nas classes de tarefa, o cancelamento envolve a cooperação entre o delegado de usuário, que representa uma operação cancelável e o código que solicitou o cancelamento.In the Task classes, cancellation involves cooperation between the user delegate, which represents a cancelable operation, and the code that requested the cancellation. Um cancelamento bem-sucedido envolve o código de solicitação que chama o CancellationTokenSource.Cancel método e o delegado do usuário encerrando a operação em tempo hábil.A successful cancellation involves the requesting code calling the CancellationTokenSource.Cancel method and the user delegate terminating the operation in a timely manner. Você pode terminar a operação ao usar uma destas opções:You can terminate the operation by using one of these options:

  • Simplesmente ao sair do delegado.By simply returning from the delegate. Em muitos cenários isso é suficiente. Entretanto, uma instância da tarefa que é cancelada desse modo faz a transição para o estado TaskStatus.RanToCompletion, e não para o estado 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.

  • Ao gerar um OperationCanceledException e passar o token em que o cancelamento foi solicitado.By throwing a OperationCanceledException and passing it the token on which cancellation was requested. O modo preferido de fazer isso é usar o método ThrowIfCancellationRequested.The preferred way to do this is to use the ThrowIfCancellationRequested method. Uma tarefa que é cancelada desse modo faz a transição para o estado Cancelado, o qual o código de chamada pode usar para verificar se a tarefa respondeu a sua solicitação de cancelamento.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.

O exemplo a seguir mostra o padrão básico para o cancelamento da tarefa que gerou a exceção.The following example shows the basic pattern for task cancellation that throws the exception. Observe que o token é passado ao delegado do usuário e à instância da tarefa em si.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

Para obter um exemplo mais completo, confira Como cancelar uma tarefa e seus filhos.For a more complete example, see How to: Cancel a Task and Its Children.

Quando uma instância de tarefa observa uma OperationCanceledException gerada pelo código de usuário, compara o token de exceção ao token associado (aquele que foi passado para a API que criou a tarefa).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). Se eles forem os mesmos e a propriedade IsCancellationRequested do token retornar verdadeiro, a tarefa interpretará isso como o cancelamento da confirmação e fará a transição para o estado cancelado.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. Se você não usar um método Wait ou WaitAll para aguardar a conclusão da tarefa, a tarefa apenas definirá seu status como 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.

Se você estiver aguardando uma tarefa que faça a transição para o estado Cancelado, uma exceção System.Threading.Tasks.TaskCanceledException (envolvida em uma exceção AggregateException) será lançada.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. Observe que essa exceção indica o cancelamento com êxito em vez de uma situação de falha.Note that this exception indicates successful cancellation instead of a faulty situation. Assim, a propriedade Exception da tarefa retorna null.Therefore, the task's Exception property returns null.

Se a propriedade IsCancellationRequested do token retornar falso ou se o token de exceção não corresponder ao token da tarefa, OperationCanceledException será tratada como uma exceção normal, fazendo com que a tarefa transicione para o estado de Falha.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. Observe também que a presença de outras exceções também fará com que a tarefa faça a transição para o estado de Falha.Also note that the presence of other exceptions will also cause the Task to transition to the Faulted state. Você poderá obter o status da tarefa concluída na propriedade Status.You can get the status of the completed task in the Status property.

É possível que uma tarefa continue a processar alguns itens após o cancelamento ser solicitado.It is possible that a task may continue to process some items after cancellation is requested.

Confira tambémSee also