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
Description
.NET 6.0 introduced an undocumented breaking change. IHostedService startup is now special-cased for
BackgroundService, where the Host takes a direct dependency onBackgroundService.ExecuteTask, which can be null in some cases that previously worked.runtime/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs
Lines 80 to 84 in 6195d98
When
BackgroundService.ExecuteTaskis null (e.g. because the override forBackgroundService.StartAsyncdecided not to call the base impl), this throws aNullReferenceExceptionand causes the Host to abort (instead of previous behavior whereIHostedService.StartAsyncwas called and that was it.Example BackgroundService impl that breaks
Configuration
Regression?
Yes, this is a breaking change in .NET 6. Previous versions did not special-case
BackgroundService, and instead treated allIHostedService'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