C# CancellationTokenSource

Resumo : neste tutorial, você aprenderá como usar C# CancellationTokenSourcepara cancelar uma operação assíncrona.

O cancelamento é cooperativo

No .NET, o cancelamento é cooperativo. Isso significa que quando você solicita o cancelamento de uma operação assíncrona, cabe ao código que executa essa operação verificar se o cancelamento foi solicitado e interromper a execução, caso tenha sido.

Além disso, o cancelamento não é algo aplicado automaticamente pelo .NET, mas sim um mecanismo que você deve implementar manualmente em seu código usando um CancellationTokenobjeto.

Em outras palavras, se você deseja que uma operação assíncrona seja cancelável, na operação, você precisa verificar explicitamente as solicitações de cancelamento usando a IsCancellationRequestedpropriedade do CancellationTokenobjeto e interromper a execução se ela retornar true.

Para criar um CancellationToken, você usa a CancellationTokenSourceclasse.

Como usar a classe CancellationTokenSource

Aqui estão as etapas para usar a CancellationTokenSourceclasse:

Primeiro, crie um novo CancellationTokenSourceobjeto que possa ser usado para gerar um token de cancelamento:

var cts = new CancellationTokenSource();Linguagem de código:  C#  ( cs )

Segundo, passe o token de cancelamento para uma operação assíncrona:

AsyncOperation(cts.Token);Linguagem de código:  C#  ( cs )

Terceiro, verifique as solicitações de cancelamento na operação assíncrona e interrompa a execução se o cancelamento tiver sido solicitado:

Task<T> AsyncOperation(CancellationToken cancellationToken)
{
    while (!cancellationToken.IsCancellationRequested)
    {
        // Do some work...
    }

    // The operation was cancelled...
}Linguagem de código:  C#  ( cs )

Por fim, cancelamos o sinal usando o método Cancel() do CancellationTokenSourceobjeto:

cts.Cancel();Linguagem de código:  C#  ( cs )

Exemplo de CancellationTokenSource em C#

using static System.Console;

static List<int> Square(int max, CancellationToken token)
{
    var result = new List<int>();
    for (int i = 0; i < max; i++)
    {
        Thread.Sleep(500);

        if (token.IsCancellationRequested)
        {
            WriteLine("Cancellation requested!!!");
            token.ThrowIfCancellationRequested();
            break;
        }

        var square = i * i;

        WriteLine(square);
        result.Add(square);
    }
    return result;
}

CancellationTokenSource cts = new();

var task = Task.Run(() => Square(10, cts.Token));
task.ContinueWith((t) =>
{
    var squares = t.Result;
    WriteLine("The square numbers are");
    foreach (var square in squares)
    {
        Write($"{square} ");
    }
}, TaskContinuationOptions.OnlyOnRanToCompletion);


WriteLine("Press 'c' to cancel.");
while (true)
{
    var keyInfo = ReadKey(true);
    if (keyInfo.KeyChar == 'c')
    {
        if (task.Status == TaskStatus.Running)
        {
            cts.Cancel();
            WriteLine("Canceling the task...");
            break;
        }
    }
    // quit if the task has been completed
    if (task.Status == TaskStatus.RanToCompletion)
    {
        break;
    }
}
Linguagem de código:  C#  ( cs )

Saída:

Press 'c' to cancel.
0
1
4
9
16
25
Canceling the task...Linguagem de código:  texto simples  ( texto simples )

Como funciona.

Primeiro, crie um CancellationTokenSourceobjeto.

CancellationTokenSource cts = new();Linguagem de código:  C#  ( cs )

Segundo, crie uma nova tarefa que execute o Square()método:

var task = Task.Run(() => Square(10, cts.Token));Linguagem de código:  C#  ( cs )

O Square()método retorna uma lista de números quadrados com base no argumento. Por exemplo, se você passar 10 para o Square()método, ele retornará uma lista de números quadrados de 1, 2, 3,… 9, que são 2, 4, 9,… 81. Além disso, passamos a CancellationTokenpara o Square()método.

Terceiro, defina o Square()método que retorna uma lista de números quadrados. O Square()método utiliza o CancellationTokenobjeto para verificar se o cancelamento foi solicitado. Se sim, ele chama token.ThrowIfCancellationRequested()o método para gerar OperationCanceledExceptione sair do loop.

Quarto, crie uma continuação que seja executada somente se a tarefa estiver sendo executada até o fim:

task.ContinueWith((t) =>
{
    var squares = t.Result;
    WriteLine("The square numbers are");
    foreach (var square in squares)
    {
        Write($"{square} ");
    }
}, TaskContinuationOptions.OnlyOnRanToCompletion);Linguagem de código:  C#  ( cs )

Quinto, crie um loop que verifique se o usuário pressiona a letra ce envie um cancelamento usando o Cancel()método do CancellationTokenSourceobjeto e saia do loop. Além disso, se o status da tarefa for RanToCompletion, saia do loop:

WriteLine("Press 'c' to cancel.");
while (true)
{
    var keyInfo = ReadKey(true);
    if (keyInfo.KeyChar == 'c')
    {
        if (task.Status == TaskStatus.Running)
        {
            cts.Cancel();
            WriteLine("Canceling the task...");
            break;
        }
    }
    // quit if the task has been completed
    if (task.Status == TaskStatus.RanToCompletion)
    {
        break;
    }
}Linguagem de código:  C#  ( cs )

Resumo

  • Use C# CancellationTokenSourcepara cancelar uma operação assíncrona executada por uma tarefa.

Deixe um comentário

O seu endereço de email não será publicado. Campos obrigatórios marcados com *