Я столкнулся с ситуацией, когда метод Task.Delay()
вызовет событие отмены в IApplicationLifetime
. Вот код:
static async Task Main(string[] args)
{
Console.WriteLine("Starting");
await BuildWebHost(args)
.RunAsync();
Console.WriteLine("Press any key to exit..");
Console.ReadKey();
}
private static IHost BuildWebHost(string[] args)
{
var hostBuilder = new HostBuilder()
.ConfigureHostConfiguration(config =>
{
config.AddEnvironmentVariables();
config.AddCommandLine(args);
})
.ConfigureAppConfiguration((hostContext, configApp) =>
{
configApp.SetBasePath(Directory.GetCurrentDirectory());
configApp.AddCommandLine(args);
})
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<BrowserWorkerHostedService>();
services.AddHostedService<EmailWorkerHostedService>();
})
.UseConsoleLifetime();
return hostBuilder.Build();
}
и вот размещенные службы, которые ненормально останавливаются:
public class BrowserWorkerHostedService : BackgroundService
{
private IApplicationLifetime _lifetime;
private IHost _host;
public BrowserWorkerHostedService(
IApplicationLifetime lifetime,
IHost host)
{
this._lifetime = lifetime;
this._host = host;
}
protected override async Task ExecuteAsync(CancellationToken stopToken)
{
while (!_lifetime.ApplicationStarted.IsCancellationRequested
&& !_lifetime.ApplicationStopping.IsCancellationRequested
&& !stopToken.IsCancellationRequested)
{
Console.WriteLine($"{nameof(BrowserWorkerHostedService)} is working. {DateTime.Now.ToString()}");
//lifetime.StopApplication();
//await StopAsync(stopToken);
await Task.Delay(1_000, stopToken);
}
Console.WriteLine($"End {nameof(BrowserWorkerHostedService)}");
await _host.StopAsync(stopToken);
}
}
public class EmailWorkerHostedService : BackgroundService
{
private IApplicationLifetime _lifetime;
private IHost _host = null;
public EmailWorkerHostedService(
IApplicationLifetime lifetime,
IHost host)
{
this._lifetime = lifetime;
this._host = host;
}
protected override async Task ExecuteAsync(CancellationToken stopToken)
{
while (!_lifetime.ApplicationStarted.IsCancellationRequested
&& !_lifetime.ApplicationStopping.IsCancellationRequested
&& !stopToken.IsCancellationRequested)
{
Console.WriteLine($"{nameof(EmailWorkerHostedService)} is working. {DateTime.Now.ToString()}");
await Task.Delay(1_000, stopToken);
}
Console.WriteLine($"End {nameof(EmailWorkerHostedService)}");
await _host.StopAsync(stopToken);
}
}
Я бы хотел, чтобы мои службы работали, если не запущен lifetime.StopApplication()
. Однако размещенные службы останавливаются, потому что переменная lifetime.ApplicationStarted.IsCancellationRequested
устанавливается на true
после второго изменения. Хотя теоретически у меня нет кода, который явно прерывает приложение.
Журнал будет выглядеть так:
Запуск BrowserWorkerHostedService работает. 09.07.2019 17: 03: 53
EmailWorkerHostedService работает. 09.07.2019 17:03:53
Приложение запущено. Нажмите Ctrl + C, чтобы выключить.
Хостинг-среда: Производство
Путь к корню содержимого: xxxx
End EmailWorkerHostedService
End BrowserWorkerHostedService
Есть хорошее объяснение, почему Task.Delay()
вызывает событие отмены ApplicationStarted?