Resumo : neste tutorial, você aprenderá como usar C# CancellationTokenSource
para 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 CancellationToken
objeto.
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 IsCancellationRequested
propriedade do CancellationToken
objeto e interromper a execução se ela retornar true
.
Para criar um CancellationToken
, você usa a CancellationTokenSource
classe.
Como usar a classe CancellationTokenSource
Aqui estão as etapas para usar a CancellationTokenSource
classe:
Primeiro, crie um novo CancellationTokenSource
objeto 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 CancellationTokenSource
objeto:
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 CancellationTokenSource
objeto.
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 CancellationToken
para o Square()
método.
Terceiro, defina o Square()
método que retorna uma lista de números quadrados. O Square()
método utiliza o CancellationToken
objeto para verificar se o cancelamento foi solicitado. Se sim, ele chama token.ThrowIfCancellationRequested()
o método para gerar OperationCanceledException
e 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 c
e envie um cancelamento usando o Cancel()
método do CancellationTokenSource
objeto 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#
CancellationTokenSource
para cancelar uma operação assíncrona executada por uma tarefa.