diff --git a/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs b/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs
index 4041133a0a9f25..2f73146e695ef2 100644
--- a/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs
+++ b/src/libraries/Microsoft.Extensions.Hosting/src/Internal/Host.cs
@@ -79,15 +79,22 @@ public async Task StartAsync(CancellationToken cancellationToken = default)
private async Task TryExecuteBackgroundServiceAsync(BackgroundService backgroundService)
{
+ // backgroundService.ExecuteTask may not be set (e.g. if the derived class doesn't call base.StartAsync)
+ Task backgroundTask = backgroundService.ExecuteTask;
+ if (backgroundTask == null)
+ {
+ return;
+ }
+
try
{
- await backgroundService.ExecuteTask.ConfigureAwait(false);
+ await backgroundTask.ConfigureAwait(false);
}
catch (Exception ex)
{
// When the host is being stopped, it cancels the background services.
// This isn't an error condition, so don't log it as an error.
- if (_stopCalled && backgroundService.ExecuteTask.IsCanceled && ex is OperationCanceledException)
+ if (_stopCalled && backgroundTask.IsCanceled && ex is OperationCanceledException)
{
return;
}
diff --git a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs
index d07c2bc57eaa71..b3133dba3be886 100644
--- a/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs
+++ b/src/libraries/Microsoft.Extensions.Hosting/tests/UnitTests/Internal/HostTests.cs
@@ -1394,6 +1394,36 @@ public async Task HostNoErrorWhenServiceIsCanceledAsPartOfStop()
}
}
+ ///
+ /// Tests that when a BackgroundService does not call base, the Host still starts and stops successfully.
+ ///
+ [Fact]
+ public async Task StartOnBackgroundServiceThatDoesNotCallBase()
+ {
+ TestLoggerProvider logger = new TestLoggerProvider();
+
+ using IHost host = CreateBuilder()
+ .ConfigureLogging(logging =>
+ {
+ logging.AddProvider(logger);
+ })
+ .ConfigureServices(services =>
+ {
+ services.AddHostedService();
+ })
+ .Build();
+
+ host.Start();
+ await host.StopAsync();
+
+ foreach (LogEvent logEvent in logger.GetEvents())
+ {
+ Assert.True(logEvent.LogLevel <= LogLevel.Information, "All logged events should be less than or equal to Information. No Warnings or Errors.");
+
+ Assert.NotEqual("BackgroundServiceFaulted", logEvent.EventId.Name);
+ }
+ }
+
private IHostBuilder CreateBuilder(IConfiguration config = null)
{
return new HostBuilder().ConfigureHostConfiguration(builder => builder.AddConfiguration(config ?? new ConfigurationBuilder().Build()));
@@ -1562,5 +1592,14 @@ protected override async Task ExecuteAsync(CancellationToken stoppingToken)
}
}
}
+
+ private class BackgroundServiceDoesNotCallBase : BackgroundService
+ {
+ public override Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
+
+ protected override Task ExecuteAsync(CancellationToken stoppingToken) => Task.CompletedTask;
+
+ public override Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
+ }
}
}