Due to bugs in BackgroundService I'm using Stephen Cleary's excellent workaround. It works, but I can't return a non-zero exit code upon failure.
A minimal working example (for use with the $ dotnet new worker template):
MyBackgroundService.cs
public class MyBackgroundService : BackgroundService {
private readonly IHostApplicationLifetime _lifetime;
public MyBackgroundService(IHostApplicationLifetime lifetime) => _lifetime = lifetime;
protected override Task ExecuteAsync(CancellationToken stoppingToken) => Task.Run(async () => {
try {
while (!stoppingToken.IsCancellationRequested) {
await Task.Delay(1000);
if (Random.Shared.NextDouble() < 0.5) throw new Exception("RANDOM CRASH!");
}
}
catch {
throw; // I can hit a debug breakpoint here
}
finally {
_lifetime.StopApplication();
}
});
}
Program.cs
public class Program {
public static int Main(string[] args) {
try {
var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<MyBackgroundService>();
var host = builder.Build();
host.Run();
return 0;
}
catch (Exception) {
return 1; // <----- execution never arrives here
}
}
}
When the app crashes, I expect the exit code to be 1, but it is actually the default of 0. When I debug it never enters the catch block.
What could be the reason?
It's actually because the task returned from
BackgroundService.ExecuteAsyncis ignored (as explained on my blog). So, even though you're shutting down the host, the exception is still ignored.Hosted services don't have a way to report exceptions or exit codes. Your options are:
BackgroundService-derived type that exposes itsTaskand have your main loop resolve instances of your derived type and await those tasks. This will observe exceptions from the background services.Environment.ExitCodeif they fail, similar to this code on my blog. Then yourMaincan returnvoid.Both of these approaches do an "end run" around the app lifetime because the .NET host wasn't designed to allow background service results. I use the second one myself since the same code works for both worker processes and SCM services.