When it comes to controller's action, using "await BackgroundService.StartAsync" is the wrong way for long-running tasks.
For instance, the main ussue could be request's timeout depended on proxy settings.
Here is an example how to make your BackgroundService restartable.
BackgroundService implementation:
public class MyBackgroundService: BackgroundService
{
private volatile bool _isFinished = false;
private SemaphoreSlim _semaphore = new SemaphoreSlim(0,1);
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_isFinished = false;
// DoSomeWork
_isFinished = true;
await WaitToRestartTask(stoppingToken);
}
private async Task WaitToRestartTask(CancellationToken stoppingToken)
{
// wait until _semaphore.Release()
await _semaphore.WaitAsync(stoppingToken);
// run again
await base.StartAsync(stoppingToken);
}
public void RestartTask()
{
if (!_isFinished)
throw new InvalidOperationException("Background service is still working");
// enter from _semaphore.WaitAsync
_semaphore.Release();
}
}
Controller's action (for instance):
public async Task<IActionResult> Restart()
{
var myBackgroundService= _serviceProvider.GetServices<IHostedService>()
.OfType<MyBackgroundService>()
.First();
try
{
myBackgroundService.RestartTask();
return Ok($"MyBackgroundService was restarted");
}
catch (InvalidOperationException exception)
{
return BadRequest(exception.Message);
}
}