.NET Разработчик
описание
Дневник сертифицированного .NET разработчика. Заметки, советы, новости из мира .NET и C#. Для связи: @SBenzenko Поддержать канал: - https://boosty.to/netdeveloperdiary - https://patreon.com/user?u=52551826 - https://pay.cloudtips.ru/p/70df3b3b
Лучшие посты
за три месяцабез подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
без подписи
День 2737. #ЗаметкиНаПолях #Cancellation Токен Отмены: Ошибки, Которые Незаметно Приводят к Проблемам. Окончание Начало Продолжение Ошибка № 5: Понимание необходимости связывания токенов Иногда одной операции необходимо учитывать сразу два источника отмены — токен запроса и тайм-аут, который вы добавляете. Если забыть их объединить, один из двух источников молча ничего не сделает: public async Task<Pricing> GetPricingAsync( int id, CancellationToken requestCt) { using var timeoutCts = new CancellationTokenSource(TimeSpan.FromSeconds(3)); using var linkedCts = CancellationTokenSource.CreateLinkedTokenSource(requestCt, timeoutCts.Token); // linkedCts.Token отменяется при первом из событий: // клиент отключился или после 3х секунд var resp = await _prcClient.GetAsync($"/price/{id}", linkedCts.Token); return await resp.Content .ReadFromJsonAsync<Pricing>(linkedCts.Token); } Без связывания, отдельный токен таймаута игнорирует разрывы соединения с клиентом, а отдельный токен запроса игнорирует таймаут. CreateLinkedTokenSource — решение, когда отмена должна происходить из нескольких мест. Правила Не каждому методу нужен параметр CancellationToken. Синхронное вычисление ничего не ожидает, поэтому отменять нечего. Вот некоторые правила: 1. Всё, что ожидает ввода-вывода (БД, HTTP, файл, очередь) — принимает токен, передаёт его дальше, без исключений. 2. Циклы, сильно нагружающие CPU, длящиеся более нескольких миллисекунд — периодически проверяйте ThrowIfCancellationRequested() внутри цикла, а не только при входе. 3. Работа «fire-and-forget» — никогда не используйте RequestAborted. Используйте ApplicationStopping или лучше, передайте запрос в соответствующую фоновую очередь вместо _ = SomeAsync(…). 4. Логирование отмены — LogDebug или ниже, никогда не LogError. Это не ошибка. FAQ 1. В чем разница между CancellationToken.None и не передачей токена? На практике это приводит к одному результату — операцию нельзя отменить. Преднамеренная передача CancellationToken.None должна быть редкой и осознанной, например, в фоновый сервис, работающий вне контекста запроса, который действительно должен завершить работу независимо от обстоятельств. 2. Использовать HttpContext.RequestAborted напрямую или параметр CancellationToken? Параметр. Привязка модели ASP.NET Core автоматически заполняет параметр значением RequestAborted, и это выглядит чище, чем обращение к HttpContext. Используйте HttpContext.RequestAborted в коде, не имеющем прямого доступа к параметру, например, для фильтра или промежуточного ПО. 3. Почему мой BackgroundService останавливается посреди выполнения пакета при повторном развертывании? Потому что токен остановки срабатывает при ApplicationStopping, а таймаут завершения работы хоста по умолчанию короткий. Если пакет должен завершиться корректно, либо уменьшите размер пакета так, чтобы одна единица работы поместилась в окно завершения, либо увеличьте HostOptions.ShutdownTimeout — но не полагайтесь на неограниченный таймаут завершения, поскольку хост (или ваш оркестратор) в итоге принудительно завершит процесс независимо от этого. 4. Перехват исключения OperationCanceledException без повторного выбрасывания что-либо ломает? Зависит от места. Внутри обработчика запроса, если проигнорировать его без повторного выбрасывания, ASP.NET Core никогда не получит сигнал об отмене запроса, поэтому может попытаться отправить ответ на уже разорванное соединение, что вызовет собственное исключение на более высоком уровне. Повторно выбросьте исключение и позвольте фреймворку обработать жизненный цикл ответа; перехватывайте его локально только для добавления отладочного лога или очистки ресурса. Источник: https://thecodeman.net/posts/cancellation-tokens-in-aspnet-core-mistakes