← Назад к вопросам

Что такое cancellation token в многопоточности?

1.0 Junior🔥 151 комментариев
#Асинхронность и многопоточность

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI7 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Что такое CancellationToken в контексте многопоточности и асинхронного программирования?

CancellationToken — это механизм в .NET для безопасной и кооперативной отмены длительных операций, особенно в многопоточных и асинхронных сценариях. Это структура (struct), которая позволяет распространять уведомление об отмене между потоками, задачами (Task) или асинхронными операциями без принудительного прерывания потоков (в отличие от устаревшего Thread.Abort()).

Основное назначение и принцип работы

Основная цель — реализация кооперативной отмены, где выполняемая операция периодически проверяет флаг отмены и корректно завершает свою работу, освобождая ресурсы. Это критически важно для:

  • Отмены операций по запросу пользователя
  • Ограничения времени выполнения (timeout)
  • Остановки фоновых задач при завершении приложения

Источником токена является CancellationTokenSource, который создает и управляет состоянием одного или нескольких CancellationToken.

// Создание источника токена
CancellationTokenSource cts = new CancellationTokenSource();

// Получение токена из источника
CancellationToken token = cts.Token;

// Запуск задачи с передачей токена
Task.Run(() => LongOperation(token), token);

// Инициирование отмены (где-то в другом месте кода)
cts.Cancel();

Ключевые методы и свойства

Свойства токена:

  • IsCancellationRequested — флаг, указывающий, была ли запрошена отмена
  • CanBeCanceled — указывает, может ли данный токен перейти в состояние отмены
  • WaitHandle — объект синхронизации, который можно использовать для ожидания отмены

Основные методы:

  • ThrowIfCancellationRequested() — генерирует OperationCanceledException, если отмена запрошена
  • Register() — регистрирует делегат, который будет вызван при отмене (для cleanup-логики)

Пример использования в асинхронной операции

public async Task ProcessDataAsync(CancellationToken cancellationToken)
{
    for (int i = 0; i < 100; i++)
    {
        // Проверка отмены с выбросом исключения
        cancellationToken.ThrowIfCancellationRequested();
        
        // Или проверка с корректным завершением
        if (cancellationToken.IsCancellationRequested)
        {
            Console.WriteLine("Операция отменена, выполняется cleanup...");
            // Освобождение ресурсов
            return;
        }
        
        await ProcessItemAsync(i);
        await Task.Delay(100, cancellationToken); // Task.Delay тоже поддерживает отмену
    }
}

// Регистрация callback при отмене
cancellationToken.Register(() =>
{
    Console.WriteLine("Выполняется cleanup при отмене операции");
    // Закрытие файлов, соединений и т.д.
});

Сценарии использования

  1. Отмена по timeout:
// Автоматическая отмена через 5 секунд
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
await LongRunningOperationAsync(cts.Token);
  1. Объединение нескольких источников отмены:
var userCancellation = new CancellationTokenSource();
var timeoutCancellation = new CancellationTokenSource(TimeSpan.FromSeconds(30));

// Объединение токенов: операция отменится при любой из причин
var linkedTokenSource = CancellationTokenSource.CreateLinkedTokenSource(
    userCancellation.Token, 
    timeoutCancellation.Token
);
  1. Отмена нескольких операций одновременно:
var cts = new CancellationTokenSource();
var token = cts.Token;

// Запуск нескольких задач с одним токеном
var tasks = new List<Task>
{
    Task.Run(() => Operation1(token), token),
    Task.Run(() => Operation2(token), token),
    Task.Run(() => Operation3(token), token)
};

// Отмена ВСЕХ операций одной командой
cts.Cancel();

Преимущества перед альтернативными подходами

  1. Безопасность — не принуждает потоки к немедленной остановке
  2. Кооперативность — задача сама решает, когда проверить отмену
  3. Распространение — один токен можно передать в цепочку вызовов
  4. Композиция — возможность объединения нескольких токенов
  5. Resource cleanup — гарантирует возможность освобождения ресурсов

Важные практики

  • Всегда передавайте токен в асинхронные методы, если они поддерживают отмену
  • Не блокируйте в обработчиках Register() — это может задержать отмену
  • Освобождайте CancellationTokenSource через Dispose() или using
  • Обрабатывайте OperationCanceledException на верхнем уровне для корректного завершения

Отличия от Thread.Abort()

CancellationTokenThread.Abort()
Кооперативная отменаПринудительная остановка
Безопасна для состояния приложенияМожет оставить данные в некорректном состоянии
Позволяет cleanupНет гарантии выполнения cleanup
Не портит стек потокаВызывает ThreadAbortException в любом месте

CancellationToken стал стандартным способом обработки отмены в .NET, особенно с распространением async/await паттерна. Его правильное использование значительно повышает надежность и отзывчивость многопоточных приложений, позволяя пользователям прерывать длительные операции без риска повреждения состояния приложения.

Что такое cancellation token в многопоточности? | PrepBro