I'm developing a worker-service application using .net7, and I'm able to run it as a unit on systemd.
I wish to have the application execute some code to gracefully shutdown, whenever a 'systemctl stop my.service' is issued, however it seems like it immediately shuts down
Program.cs:
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
private readonly IConfiguration _config;
public Worker(ILogger<Worker> logger, IConfiguration config)
{
_logger = logger;
_config = config;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("{env} - Worker running at: {time}",_config["env"], DateTimeOffset.Now);
await Task.Delay(5000, stoppingToken);
}
_logger.LogInformation("this line is never executed after stop");
}
public override async Task StopAsync(CancellationToken stoppingToken)
{
await base.StopAsync(stoppingToken);
_logger.LogInformation("this line is actually executed after stop");
}
}
Both the output from inside the loop and the StopAsync are being printed successfully during run time and stop, I use the following to access it:
journalctl --unit=my.service -n 50 --no-pager
Both the output from inside the loop and the StopAsync are being printed successfully during run time and stop
Right, so it is exiting gracefully. The base.StopAsync
is cancelling the token passed to ExecuteAsync
. This almost always causes Task.Delay
to throw an OperationCanceledException
, causing the ExecuteAsync
to complete.
If you want code in ExecuteAsync
to always try to run during shutdown, put it in a finally
block.