TGViewer
.NET Разработчик .NET Разработчик @netdeveloperdiary · 6.76K subscribers
Post #1628 1.45K
День 1311. #ЗаметкиНаПолях #AsyncTips
Взаимодействие с другими системами отмены

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

Решение
У типа CancellationToken существует два основных способа реакции на запрос на отмену: периодический опрос и обратные вызовы. Периодический опрос обычно используется для кода, интенсивно использующего процессор, — например, циклов обработки данных; обратные вызовы обычно используются во всех остальных ситуациях. Регистрация обратного вызова для маркера осуществляется методом CancellationToken.Register.

Допустим, вы пишете обертку для System.Net.NetworkInformation.Pingtype и хотите предусмотреть возможность отмены тестового опроса. Класс Ping уже имеет API на базе Task, но не поддерживает CancellationToken. Вместо этого тип Ping содержит собственный метод SendAsyncCancel, который может использоваться для отмены. Для этого зарегистрируйте обратный вызов, который активизирует этот метод:
async Task<PingReply> PingAsync(
string host,
CancellationToken ct)
{
using var ping = new Ping();
var task = ping.SendPingAsync(host);

using CancellationTokenRegistration _ =
ct.Register(() => ping.SendAsyncCancel());

return await task;
}

Теперь при запросе на отмену CancellationToken вызовет метод SendAsyncCancel за вас, отменяя метод SendPingAsync.

Метод CancellationToken.Register может использоваться для взаимодействия с любой альтернативной системой отмены. Но следует помнить, что, если метод получает CancellationToken, запрос отмены должен отменять только эту одну операцию. Некоторые альтернативные системы отмены реализуют отмену закрытием некоторого ресурса, что может привести к отмене нескольких операций; эта разновидность системы отмены плохо соответствует CancellationToken. Если вы решите инкапсулировать такую разновидность отмены в CancellationToken, следует документировать её необычную семантику отмены.

Помните о сроке существования регистрации обратных вызовов. Метод Register возвращает отменяемый объект, который должен быть освобожден, когда обратный вызов перестанет быть нужным. Предыдущий пример использует команду using для выполнения очистки при завершении асинхронной операции. Если в коде отсутствует команда using, то при каждом вызове кода с тем же (долгосрочным) маркером CancellationToken он будет добавлять новый обратный вызов (который, в свою очередь, будет поддерживать существование объекта Ping). Чтобы избежать утечки памяти и ресурсов, очищайте регистрацию обратного вызова, когда он перестаёт быть нужным.

Источник: Стивен Клири “Конкурентность в C#”. 2-е межд. изд. — СПб.: Питер, 2020. Глава 10.
  • 👍 8
More from @netdeveloperdiary
  1. Oct 13, 2026День 2813. #ЗаметкиНаПолях #Async Ещё Раз Про Async/Await в C#. Часть 1 1. Почему существу…
  2. Oct 12, 2026День 2812. #Карьера #AI Как Разработчикам Оставаться Полезными, Когда Код Пишет ИИ? По мер…
  3. Oct 11, 2026День 2811. #ВопросыНаСобеседовании Марк Прайс предложил свой набор из 60 вопросов (как тех…
  4. Oct 10, 2026День 2810. #ЧтоНовенького #VSCode Более Быстрый и Лёгкий C# Dev Kit Мы, разработчики, люби…
  5. Oct 9, 2026День 2809. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Окончание Начало 3.…
  6. Oct 8, 2026День 2808. #Карьера 5 Навыков, Которые Помогут Быстрее Стать Сеньором. Начало В ИТ есть се…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →