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

Что произойдет при сбросе CancellationToken?

2.0 Middle🔥 171 комментариев
#Асинхронность и многопоточность

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

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

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

Реакция на сброс CancellationToken

Когда происходит сброс CancellationToken, это означает, что свойство IsCancellationRequested объекта становится true. Этот сигнал предназначен для кооперативной отмены (cooperative cancellation) — выполнения кода, который может регулярно проверять этот флаг и корректно завершить свою работу, а не для немедленного прерывания потока.

Механизм работы и воздействие

  1. Изменение состояния токена: Сам токен становится "сброшенным". Все связанные токены (например, созданные через CancellationTokenSource.CreateLinkedTokenSource) также получают этот сигнал.
  2. Запуск делегатов: Если к токену были зарегистрированы callback-делегаты через метод Register, они будут выполнены. Это позволяет выполнить дополнительную логику при отмене — например, освобождение ресурсов.
  3. Генерация исключения: При использовании метода ThrowIfCancellationRequested() в контексте проверяемого кода, если токен сброшен, будет выброшено исключение OperationCanceledException (или TaskCanceledException в задачах). Это стандартный способ прервать выполнение с обработкой исключения.
  4. Взаимодействие с Task: Для задач (Task), которые были созданы с использованием этого токена, будет автоматически произведена отмена, если задача еще не началась или находится в состоянии ожидания. Если задача уже выполняется, она должна самостоятельно проверять токен.

Пример поведения кода при сбросе

Рассмотрим пример задачи, которая реагирует на сброс токена:

CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;

Task task = Task.Run(() =>
{
    for (int i = 0; i < 100; i++)
    {
        // Проверяем состояние токена
        if (token.IsCancellationRequested)
        {
            // Выполняем корректное завершение
            Console.WriteLine("Операция прервана.");
            return; // или throw new OperationCanceledException(token);
        }
        token.ThrowIfCancellationRequested(); // Альтернативный способ

        Console.WriteLine($"Шаг {i}");
        Thread.Sleep(100);
    }
}, token);

// Сброс токена через 500 мс
cts.CancelAfter(500);

try
{
    task.Wait();
}
catch (AggregateException ae)
{
    ae.Handle(e => e is OperationCanceledException);
    Console.WriteLine("Задача была отменена.");
}

При сбросе токена через cts.Cancel() или CancelAfter:

  • Токен переходит в состояние IsCancellationRequested = true.
  • В теле задачи проверка token.IsCancellationRequested или ThrowIfCancellationRequested() приведет к завершению работы (возврату или исключению).
  • Задача переходит в состояние Canceled (если завершилась через исключение OperationCanceledException), что можно проверить через task.Status.

Важные особенности и рекомендации

  • Не мгновенное прерывание: Сброс токена не прерывает выполнение потока или метода немедленно, как Thread.Abort. Это лишь сигнал, который должен быть обработан кодом.
  • Освобождение ресурсов: Используйте регистрацию callback через Register для гарантированного освобождения ресурсов (например, закрытия файлов, сетевых соединений).
  • Проверка в циклах и длительных операциях: Регулярная проверка токена обязательна в длительных операциях, особенно в циклах или при ожидании внешних ресурсов.
  • Исключения и обработка ошибок: Исключение OperationCanceledException должно корректно обрабатываться в вышестоящем коде, чтобы отличать отмену операции от других ошибок.
  • Связь с async методами: В асинхронных методах токен часто передается как параметр и используется для отмены асинхронных операций, например, в методах HttpClient или при работе с базами данных.

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