Reputation: 344
I need to run different instances of a Worker Service (BackgroundService
): same code but different configuration.
The number of instances and the start and stop of every instance will change during the running process.
So my choice was to write 2 programs:
WorkerProgram
: the Worker ServiceMainProgram
: manage (start and stop) of every different instance of WorkerProgram
Sample code of WorkerProgram
:
var host = Host.CreateDefaultBuilder()
.ConfigureServices(services =>
{
services.AddSingleton(new Instance { Id = int.Parse(args[0])});
services.AddHostedService<Worker>();
})
.Build();
await host.RunAsync();
public class Worker : BackgroundService
{
private readonly Instance _instance;
public Worker(Instance instance)
{
_instance = instance;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Running {}", _instance.Id);
await Task.Delay(10000, stoppingToken);
_logger.LogInformation("END");
}
}
}
MainProgram
starts every WorkerProgram
using
var process = new Process();
process.StartInfo.Filename = "WorkerProgram.exe";
process.StartInfo.Arguments = i.ToString();
process.Start();
so every Worker Service run in a different process.
But when it needs to stop them, the command
process.Kill();
will Kill the process in the middle of run.
How can I stop the process in a better way (eg. using CancellationToken)?
Thank you!
My current (bad) solution is to create a placeholder file for every BackgroundService. And check the existence of the file at every cicle.
Upvotes: 3
Views: 766
Reputation: 1062780
untested, but:
cancellationToken.ThrowIfCancellationRequested();
process.Start();
using (cancellationToken.Register(static state => {
try {
(state as Process)?.Close(); // or Kill, or both; your choice
} catch (Exception ex) {
// best efforts only
Debug.WriteLine(ex.Message);
}
}, process))
{
await process.WaitForExitAsync(cancellationToken);
}
The Register
here will deal with killing the process in the cancellation case; if the external process exits before then, we will unregister via the using
after the WaitForExitAsync
, and won't attempt to kill it.
Upvotes: 0