-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Description
.NET 6.0 introduced an undocumented breaking change. IHostedService startup is now special-cased for BackgroundService, where the Host takes a direct dependency on BackgroundService.ExecuteTask, which can be null in some cases that previously worked.
| private async Task TryExecuteBackgroundServiceAsync(BackgroundService backgroundService) | |
| { | |
| try | |
| { | |
| await backgroundService.ExecuteTask.ConfigureAwait(false); |
When BackgroundService.ExecuteTask is null (e.g. because the override for BackgroundService.StartAsync decided not to call the base impl), this throws a NullReferenceException and causes the Host to abort (instead of previous behavior where IHostedService.StartAsync was called and that was it.
Example BackgroundService impl that breaks
class MyBackgroundService : BackgroundService
{
public override Task StartAsync(CancellationToken cancellation)
{
return Task.CompletedTask;
}
protected override Task ExecuteAsync(CancellationToken stoppingToken)
{
return Task.CompletedTask;
}
}Configuration
- Which version of .NET is the code running on? .NET 6.0.100-rc.1.21463.6
- What OS and version, and what distro if applicable? Windows 10, but issue is not platform-specific
- What is the architecture (x64, x86, ARM, ARM64)? x64, but issue is not platform-specific
- Do you know whether it is specific to that configuration? Not platform-specific
Regression?
Yes, this is a breaking change in .NET 6. Previous versions did not special-case BackgroundService, and instead treated all IHostedService's uniformly. The new behavior IMHO violates the Principle of Least Astonishment.
Other information
Breaking change was introduced in #42981
Expectations for this issue
Either fix the regression, or document it as a breaking change in https://docs.microsoft.com/en-us/dotnet/core/compatibility/6.0