Compartilhar via


Cancelamento da tarefa

O System.Threading.Tasks.Task e System.Threading.Tasks.Task<TResult> classes oferecem suporte a cancelamento através do uso de tokens de cancelamento, o que são novos na .NET Framework 4. Para obter mais informações, consulte Cancelamento. As classes de tarefa, cancelamento envolve a cooperação entre o representante do usuário, que representa uma operação pode ser cancelada e o código que solicitou o cancelamento. Um cancelamento bem-sucedida envolve a chamada do código solicitando o CancellationTokenSource.Cancel método e o delegado de usuário, encerrando a operação em uma maneira oportuna. Você pode finalizar a operação usando uma destas opções:

  • Retornando simplesmente partir do delegado. Em muitos cenários, isso é suficiente; No entanto, uma tarefa que instância é "cancelada" dessa maneira transita para o RanToCompletion o estado, não para o estado de cancelado.

  • Lançando um OperationCanceledException e passando o token no qual o cancelamento foi solicitado. A melhor maneira de fazer isso é usar o ThrowIfCancellationRequested método. Uma tarefa que seja cancelada neste transições de forma para o estado de cancelado, o código de chamada pode usar para verificar que a tarefa respondeu a sua solicitação de cancelamento.

O exemplo a seguir mostra o padrão básico para o cancelamento da tarefa que lança a exceção. Observe que o token é passado para o representante do usuário e a instância de tarefa.

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
        End Try

        Console.ReadKey()
    End Sub
End Module
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
    static void Main()
    {

        var tokenSource2 = new CancellationTokenSource();
        CancellationToken ct = tokenSource2.Token;

        var task = Task.Factory.StartNew(() =>
        {

            // 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 StartNew.

        tokenSource2.Cancel();

        // Just continue on this thread, or Wait/WaitAll with try-catch:
        try
        {
            task.Wait();
        }
        catch (AggregateException e)
        {
            foreach (var v in e.InnerExceptions)
                Console.WriteLine(e.Message + " " + v.Message);
        }

        Console.ReadKey();
    }
}

Para um exemplo completo, consulte Como: Cancelar uma tarefa e seus filhos.

Quando uma instância de tarefa se observa um OperationCanceledException lançada pelo código do usuário, ele compara o token da exceção para o seu token associado (aquele que foi passado para a API que criou a tarefa). Se eles forem iguais e o token IsCancellationRequested propriedade retorna true, a tarefa interpreta isso como o cancelamento acknowledging e transições para o estado de cancelado. Se você não usar um Wait ou WaitAll o método de espera para a tarefa, então a tarefa define apenas o seu status para Canceled.

Se você estiver esperando uma tarefa a transição para o estado de cancelado, um TaskCanceledException (empacotada em um AggregateException) é fabricado e lançada. Observe que essa exceção indica cancelamento bem-sucedida em vez de uma situação com defeito. Portanto, a propriedade de exceção da tarefa retorna null.

Se o token IsCancellationRequested propriedade retorna false ou se o token da exceção não coincide com a tarefa do token, o OperationCanceledException é tratado como uma exceção normal, fazendo com que a tarefa de fazer a transição para o estado Faulted. Observe também que a presença de outras exceções também fará com que a tarefa a transição para o estado com falha. Você pode obter o status da tarefa concluída na Status propriedade.

É possível que uma tarefa pode continuar a processar alguns itens após o cancelamento for solicitado.

Consulte também

Tarefas

Como: Cancelar uma tarefa e seus filhos

Conceitos

Cancelamento