В .NET 11 Исключения Фоновых Сервисов Будут Всплывать
Ошибка, которая давно существовала в .NET: если BackgroundService генерировал исключение после первого await, хост перехватывал его, писал критическое сообщение в лог, а затем корректно завершал работу с кодом результата 0. Т.е. все думали, что процесс успешно завершился. Теперь это исправлено!
Проблема
Рассмотрим этот рабочий процесс:
public class Worker : BackgroundService
{
protected override async Task
ExecuteAsync(CancellationToken stopToken)
{
await Task.Delay(TimeSpan.FromSeconds(1), stopToken);
throw new Exception("something went wrong");
}
}
До .NET 11 вывод был таким:
crit: Microsoft.Extensions.Hosting.Internal.Host[10]
The HostOptions.BackgroundServiceExceptionBehavior is configured to StopHost.
A BackgroundService has thrown an unhandled exception, and the IHost instance is stopping.
...
System.Exception: something went wrong
info: Microsoft.Hosting.Lifetime[0]
Application is shutting down...
Процесс завершён с кодом 0 ??? Критическая ошибка в логе, но код результата всё равно 0.
Почему это так работало?
Если метод помечен как асинхронный, исключение перехватывалось функцией TryExecuteBackgroundServiceAsync глубоко внутри инфраструктуры, логировалось как критическое, после чего хост инициировал корректное завершение работы. Корректное завершение работы => код результата 0.
Если метод не помечен как асинхронный и выбрасывалось исключение, то процесс завершался с кодом ошибки.
Основная причина в том, что host.RunAsync() возвращает Task (а не Task<int>), и не было механизма для сигнализации о завершении процесса с кодом ошибки для фонового сервиса, который бы указывал на сбой.
Исправление в .NET 11
Теперь IHost.RunAsync() и IHost.StopAsync() будут передавать исключение из BackgroundService, а не игнорировать его. Теперь вы получите:
crit: Microsoft.Extensions.Hosting.Internal.Host[10]
…
System.Exception: something went wrong
Unhandled exception. System.Exception: something went wrong
at Worker.ExecuteAsync(…)
Process finished with exit code 134. (или 1 в Windows)
Если вам нужно старое поведение
Вы можете установить для параметра обработки исключений значение «Игнорировать»:
services.Configure<HostOptions>(options =>
{
options.BackgroundServiceExceptionBehavior = BackgroundServiceExceptionBehavior.Ignore;
});
См. оригинальный ишью.
Источник: https://steven-giesel.com/blogPost/00fcb870-6bf7-4f97-824f-8eab1b8838be/backgroundservice-exceptions-now-propagate-in-net-11