As part of #87335, there were discussions that BackgroundService implementation should be moved to StartedAsync(). This will allow other IHostedService.StartAsync() implementations to always run before backgroundservice which prevents order-of-registration issues.
Since BackgroundService already has a virtual Start() implementing IHostedService.Start(), we would keep that and explicitly implement the new IHostedLifecycleService members:
API
namespace Microsoft.Extensions.Hosting
{
- public abstract class BackgroundService : IDisposable, IHostedService
// Note that IHostedLifecycleService implements IHostedService
+ public abstract class BackgroundService : IDisposable, IHostedLifecycleService
// Keep this, but this method will no longer implement IHostedService.StartAsync
public virtual Task StartAsync(CancellationToken cancellationToken);
+ Task IHostedLifecycleService.StartingAsync(CancellationToken cancellationToken); //noop
+ Task IHostedLifecycleService.StartAsync(CancellationToken cancellationToken); //noop
+ Task IHostedLifecycleService.StartedAsync(CancellationToken cancellationToken); //noop
+ Task IHostedLifecycleService.StoppingAsync(CancellationToken cancellationToken); //noop
// We don't need to explictely implement StopAsync since the existing virtual is fine
+ Task IHostedLifecycleService.StoppedAsync(CancellationToken cancellationToken); //noop
}
Alternative
Note that by implementing the new callbacks, it prevents derived classes from also implementing them. Consider the alternative where the new callbacks are all added as virtuals, but this would be breaking since existing overrides of StartAsync will have pre- and post- behavior broken when calling base.StartAsync() since the base class implementation (BackgroundService) will no longer have any implementation:
namespace Microsoft.Extensions.Hosting
{
- public abstract class BackgroundService : IDisposable, IHostedService
+ public abstract class BackgroundService : IDisposable, IHostedLifecycleService
+ public virtual Task StartingAsync(CancellationToken cancellationToken); //noop
public virtual Task StartAsync(CancellationToken cancellationToken); //noop
+ public virtual Task StartedAsync(CancellationToken cancellationToken);
+ public virtual Task StoppingAsync(CancellationToken cancellationToken); //noop
public virtual Task StopAsync(CancellationToken cancellationToken);
+ public virtual Task StoppedAsync(CancellationToken cancellationToken); //noop
}
As part of #87335, there were discussions that BackgroundService implementation should be moved to
StartedAsync(). This will allow otherIHostedService.StartAsync()implementations to always run before backgroundservice which prevents order-of-registration issues.Since BackgroundService already has a virtual
Start()implementingIHostedService.Start(), we would keep that and explicitly implement the newIHostedLifecycleServicemembers:API
namespace Microsoft.Extensions.Hosting { - public abstract class BackgroundService : IDisposable, IHostedService // Note that IHostedLifecycleService implements IHostedService + public abstract class BackgroundService : IDisposable, IHostedLifecycleService // Keep this, but this method will no longer implement IHostedService.StartAsync public virtual Task StartAsync(CancellationToken cancellationToken); + Task IHostedLifecycleService.StartingAsync(CancellationToken cancellationToken); //noop + Task IHostedLifecycleService.StartAsync(CancellationToken cancellationToken); //noop + Task IHostedLifecycleService.StartedAsync(CancellationToken cancellationToken); //noop + Task IHostedLifecycleService.StoppingAsync(CancellationToken cancellationToken); //noop // We don't need to explictely implement StopAsync since the existing virtual is fine + Task IHostedLifecycleService.StoppedAsync(CancellationToken cancellationToken); //noop }Alternative
Note that by implementing the new callbacks, it prevents derived classes from also implementing them. Consider the alternative where the new callbacks are all added as virtuals, but this would be breaking since existing overrides of StartAsync will have pre- and post- behavior broken when calling
base.StartAsync()since the base class implementation (BackgroundService) will no longer have any implementation:namespace Microsoft.Extensions.Hosting { - public abstract class BackgroundService : IDisposable, IHostedService + public abstract class BackgroundService : IDisposable, IHostedLifecycleService + public virtual Task StartingAsync(CancellationToken cancellationToken); //noop public virtual Task StartAsync(CancellationToken cancellationToken); //noop + public virtual Task StartedAsync(CancellationToken cancellationToken); + public virtual Task StoppingAsync(CancellationToken cancellationToken); //noop public virtual Task StopAsync(CancellationToken cancellationToken); + public virtual Task StoppedAsync(CancellationToken cancellationToken); //noop }