I'll bring your attention to this comment on Microsoft.Extensions.Hosting.Internal.Hosting.StartAsync(), which is the internal call that happens during your builder.Build().Run().
/// <summary>
/// Order:
/// IHostLifetime.WaitForStartAsync
/// Services.GetService{IStartupValidator}().Validate()
/// IHostedLifecycleService.StartingAsync
/// IHostedService.Start
/// IHostedLifecycleService.StartedAsync
/// IHostApplicationLifetime.ApplicationStarted
/// </summary>
Your ExecuteAsync() is there in the middle during IHostedService.Start. The "Application started. Press Ctrl+C.. etc" happen last, during IHostApplicationLifetime.ApplicationStarted. More specifically, from ConsoleLifetime.OnApplicationStarted.
private void OnApplicationStarted()
{
Logger.LogInformation("Application started. Press Ctrl+C to shut down.");
Logger.LogInformation("Hosting environment: {EnvName}", Environment.EnvironmentName);
Logger.LogInformation("Content root path: {ContentRoot}", Environment.ContentRootPath);
}
Since that happens at the bottom, there's really nothing in the Host that comes after. Unless you start things outside of the Host.
If you want to have something to happen after all other IHostedServices have started, the best you can do is the 2nd last item on that list: IHostedLifecycleService.StartedAsync.
Which means instead of using BackgroundService, you directly implement IHostedLifecycleService
var builder = Host.CreateApplicationBuilder(args);
builder.Services
.AddHostedService<AfterService>()
.AddHostedService<Svc1>()
.AddHostedService<Svc2>();
builder.Build().Run();
public class AfterService : IHostedLifecycleService
{
private readonly ILogger<AfterService> _logger;
public AfterService(ILogger<AfterService> logger) => _logger = logger;
public Task StartingAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public async Task StartedAsync(CancellationToken cancellationToken)
{
_logger.LogInformation("This will run after ALL other IHostedServices.Start have been called");
while (!cancellationToken.IsCancellationRequested)
{
await Task.Delay(1000); // do stuff
}
}
public Task StoppingAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask;
public Task StoppedAsync(CancellationToken cancellationToken) => Task.CompletedTask;
}