Reputation: 409
I created a sample .NET Core worker serivce in below, it just threw an Exception.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace DemoWorkerService
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
throw new Exception("My Exception");
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
}
}
The above worker service process will be aborted due to the exception threw as expected.
Then I changed the Exception put it after the await statement as below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace DemoWorkerService
{
public class Worker : BackgroundService
{
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
throw new Exception("My Exception");
}
}
}
}
This time the worker service process is still ongoing after the exception has been thrown, I can even stop the process in console by pressing "Ctrl+C", here is the log information:
info: DemoWorkerService.Worker[0]
Worker running at: 01/16/2020 12:26:07 +08:00
info: Microsoft.Hosting.Lifetime[0]
Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
Content root path: C:\MyProjects\DemoWorkerService\DemoWorkerService
info: Microsoft.Hosting.Lifetime[0]
Application is shutting down...
It seems like the worker service captured the exception by itself this time, so the exception was not propagated to outer process, I don't know why the worker service will have different behaviors, which I put the exception before and after await? Is there any reason that worker service has such two different exception behaviors?
Upvotes: 2
Views: 2595
Reputation: 11153
This is by design. BackgroundService
implements IHostedService
and only returns from StartAsync
when your service has begun execution.
If any IHostedService
throws an exception during StartAsync
, then the IHost
will fail to start.
So if your BackgroundService
throws before the first await, the exception will propagate and fail the host. If you want to prevent this, you can simply call await Task.Yield()
first.
Upvotes: 1