I run an ASP.NET Core 5 API as a Windows service using IHostBuilder.UseWindowsService()
. Consider following code block to be my Main() method:
try
{
Log.Information("Starting Web Host");
if (_isService)
{
builder.UseWindowsService();
}
var host = builder.Build();
await host.RunAsync();
}
catch (Exception e)
{
Log.Fatal(e, "Host terminated unexpectedly");
}
finally
{
Log.Information("Shutting down, cancelling running actions...");
cancellationTokenSource.Cancel();
await Task.Delay(30000); // Added this line for testing, in reality it should wait for running background tasks to be finished.
Log.Information("All tasks shut down, disposing logger.");
Log.CloseAndFlush();
cancellationTokenSource.Dispose();
}
When I stop the service, I would expect that the service remains in 'stopping' state until all code in the finally block is executed, and then goes to 'stopped' state. But in reality, the service is in stopped state almost immediately but the process keeps running until the Task.Delay()
is finished. I can see in the logging that the first logline in the finally
is logged, but the second one isn't anymore. If I would restart the service, I would even see two processes running, the one that is waiting for the Task.Delay()
to finish, and the new one.
Is there anyway I can achieve it that the service only goes to stopped state when the process is stopped? I really need this otherwise the installer that installs this gives issues because the process is still running after the service is stopped.
By the time host.RunAsync()
returns, the .NET host application has already exited, so the WindowsSerciceLifetime
has already set its state to Stopped.
The cleanest solution is to restructure the code so that all your background tasks are hosted services. The host will wait for hosted services to shut down during host shutdown.
If this is not possible, then you'll need to write your own replacement for WindowsSerciceLifetime
and manually trigger the Stopped state after the host is shut down.