Представьте, что у вас есть долго выполняемая задача, которую вы хотите завершить корректно (или нет) и при этом вам нужно отслеживать сигналы отмены из нескольких источников.
Это может быть часто встречающимся кейсом в реализации
BackgroundService или IHostedService, где вы хотите отслеживать событие IHostApplicationLifetime.ApplicationStopping и также какое-то другое событие/условие.
var hostToken = IHostApplicationLifetime.ApplicationStopping;
// Какой-то другой источник для отмены, передаваемый методом
var otherToken = ...;
Теперь вы хотите создать
CancellationToken, который будет активирован при отмене любого из токенов. Но метод обычно принимает только один токен:
await Task.Delay(Timeout.Infinite, token); // Вы не можете передать два токена здесь
📌 Решение
CancellationTokenSource.CreateLinkedTokenSource создает новый
CancellationTokenSource, который будет отменен, когда любой из связанных токенов будет отменен. Вы можете передать столько токенов, сколько вам нужно, и он вернет новый CancellationTokenSource, который вы можете использовать для создания CancellationToken для вашей задачи.
using var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(hostToken, otherToken);
var linkedToken = linkedTokenSource.Token;
await Task.Delay(Timeout.Infinite, linkedToken); // Теперь вы можете передать связанный токен
Учтите, что
CancellationTokenSource является IDisposable и должен быть утилизирован, когда вы закончите работать с ним. Вы также можете отменить связанный источник токенов вручную, чтобы указать, что задача должна быть отменена. «Исходные» токены останутся неизменными, будет отменен только связанный токен.
using var t1 = new CancellationTokenSource();
using var t2 = new CancellationTokenSource();
using var t3 = CancellationTokenSource.CreateLinkedTokenSource(t1.Token, t2.Token);
t3.Cancel();
Console.WriteLine(t1.IsCancellationRequested); // False
Console.WriteLine(t2.IsCancellationRequested); // False
Console.WriteLine(t3.IsCancellationRequested); // True