Шаблоны CancellationToken и кооперативная отмена
Передавайте CancellationToken и реагируйте на него: создавайте CTS, проверяйте отмену и выбрасывайте исключение, передавайте токен асинхронным API и освобождайте ресурсы с помощью регистраций.
«Шаблоны CancellationToken и кооперативная отмена» — бесплатный урок C# Academy на CoddyKit. Это урок 1 из 3. Ты можешь прочитать весь урок бесплатно ниже — а потом практиковать его прямо в браузере с встроенным редактором кода и ИИ-репетитором 24/7. Это часть пути обучения C# Academy, и твой прогресс синхронизируется между веб-версией и приложением CoddyKit. Курс C# Academy содержит 3 уроков всего.
Кооперативная отмена
Цель: кооперативно отменять работу.
- Создайте CancellationTokenSource
- Передавайте CancellationToken дальше
- Проверяйте IsCancellationRequested или вызывайте ThrowIfCancellationRequested()
- Быстро и корректно реагируйте на отмену
Отмена по запросу вызывающего кода
Создайте CancellationTokenSource, передайте токен и отмените операцию из вызывающего кода; вызываемый метод выбросит OperationCanceledException.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
static async Task WorkAsync(CancellationToken ct)
{
// Poll occasionally; throw to end cooperatively
for (int i = 0; i < 5; i++)
{
ct.ThrowIfCancellationRequested();
Console.WriteLine("Step " + i);
await Task.Delay(100, ct); // pass token to async API
}
}
public static void Main(string[] args)
{
var cts = new CancellationTokenSource();
Task t = WorkAsync(cts.Token);
// Cancel after a short delay (simulated user action)
Thread.Sleep(180);
cts.Cancel();
try
{
t.GetAwaiter().GetResult();
}
catch (OperationCanceledException)
{
Console.WriteLine("Canceled!");
}
}
}
Передача токенов
Передавайте токен через каждый асинхронный слой, чтобы внутренние вызовы могли своевременно остановиться.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
static async Task<string> FetchAsync(CancellationToken ct)
{
await Task.Delay(80, ct); // pretend I/O
ct.ThrowIfCancellationRequested();
return "data";
}
static async Task<string> ProcessAsync(CancellationToken ct)
{
string raw = await FetchAsync(ct); // forward token
await Task.Delay(80, ct);
return raw.ToUpperInvariant();
}
public static void Main(string[] args)
{
var cts = new CancellationTokenSource();
Task<string> job = ProcessAsync(cts.Token);
cts.CancelAfter(100); // schedule a cancellation
try
{
Console.WriteLine(job.GetAwaiter().GetResult());
}
catch (OperationCanceledException)
{
Console.WriteLine("Pipeline canceled");
}
}
}
Очистка токена через Register
Используйте token.Register, чтобы добавить небольшое действие очистки, выполняемое при поступлении запроса на отмену.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
static async Task UseRegistrationAsync(CancellationToken ct)
{
using (ct.Register(() => Console.WriteLine("Cleanup: releasing temp resources")))
{
for (int i = 0; i < 3; i++)
{
ct.ThrowIfCancellationRequested();
await Task.Delay(120, ct);
Console.WriteLine("Tick " + i);
}
}
}
public static void Main(string[] args)
{
var cts = new CancellationTokenSource();
Task t = UseRegistrationAsync(cts.Token);
Thread.Sleep(150);
cts.Cancel();
try { t.GetAwaiter().GetResult(); }
catch (OperationCanceledException) { Console.WriteLine("Canceled with cleanup"); }
}
}
Связанные источники
CreateLinkedTokenSource объединяет несколько сигналов (например, отмену пользователем и тайм-аут) в один токен.
using System;
using System.Threading;
using System.Threading.Tasks;
public class Program
{
static async Task WorkAsync(CancellationToken ct)
{
await Task.Delay(500, ct);
Console.WriteLine("Finished work");
}
public static void Main(string[] args)
{
var parent = new CancellationTokenSource();
var timeout = new CancellationTokenSource();
timeout.CancelAfter(200);
// Link both sources: cancel if parent OR timeout requests
var linked = CancellationTokenSource.CreateLinkedTokenSource(parent.Token, timeout.Token);
Task t = WorkAsync(linked.Token);
try { t.GetAwaiter().GetResult(); }
catch (OperationCanceledException) { Console.WriteLine("Canceled by parent/timeout"); }
finally { linked.Dispose(); parent.Dispose(); timeout.Dispose(); }
}
}
Рекомендации
Советы:
- Передавайте токены в асинхронные API (Task.Delay, операции ввода-вывода), чтобы они своевременно останавливались.
- Выбрасывайте OperationCanceledException для завершения работы; не подавляйте это исключение.
- Освобождайте CancellationTokenSource, если он владеет таймерами или регистрациями.
- Обработчики должны выполняться быстро; в Register выполняйте минимум работы.
Правило кооперативной отмены
Итоги
Итоги: делайте отмену кооперативной — передавайте токены, проверяйте состояние или вызывайте ThrowIfCancellationRequested, добавляйте небольшую очистку и связывайте источники для объединения сигналов.
Часто задаваемые вопросы
Урок «Шаблоны CancellationToken и кооперативная отмена» бесплатный?
Да — полный текст урока «Шаблоны CancellationToken и кооперативная отмена» бесплатно доступен здесь в веб-версии. Чтобы практиковать его интерактивно (встроенный редактор кода и ИИ-репетитор 24/7) и разблокировать остальной курс C# Academy, подпишись на CoddyKit PRO. Курс C# Academy содержит 3 уроков всего.
Чему я научусь в уроке «Шаблоны CancellationToken и кооперативная отмена»?
Передавайте CancellationToken и реагируйте на него: создавайте CTS, проверяйте отмену и выбрасывайте исключение, передавайте токен асинхронным API и освобождайте ресурсы с помощью регистраций. Ты практикуешь C# Academy с помощью реального кода, который запускаешь прямо в браузере, и ИИ-репетитор 24/7 отвечает на твои вопросы во время урока.
Нужен ли мне опыт, чтобы начать C# Academy?
Предыдущий опыт не требуется. C# Academy на CoddyKit структурирован для всех уровней — от новичков до продвинутых, поэтому ты можешь начать отсюда или с самого начала и учиться в своем темпе. Это урок 1 из 3.
Сколько времени занимает урок «Шаблоны CancellationToken и кооперативная отмена»?
Большинство уроков CoddyKit занимают около 5–10 минут. Каждый из них компактный и интерактивный, поэтому ты постоянно делаешь прогресс и продолжаешь с того же места в веб-версии и приложении.
Можно ли писать и запускать код в этом уроке C# Academy?
Да. Каждый урок C# Academy включает встроенный редактор кода, поэтому ты пишешь и запускаешь реальный код прямо в браузере и получаешь моментальную обратную связь от AI — локальная установка не требуется.
Все уроки этого курса
- Шаблоны CancellationToken и кооперативная отмена
- Тайм-ауты, IProgress и асинхронные освобождаемые ресурсы (эмуляция)
- Основы устойчивости: повторные попытки и интервалы между ними