To run some async code before the host get started.
There has been post talking about various techniques before Microsoft.Extensions.Hosting
version 8.0.0
. For example: https://andrewlock.net/running-async-tasks-on-app-startup-in-asp-net-core-part-1/.
The problem was, it was kind of hard to:
- Find a sweet spot to run the code;
- And by sweet spot, I mean, after all the services in the dependency injection containers are registered but before any hosting code's running.
- Run asynchronous but avoid async over sync.
Now, everything becomes much easier as long as Microsoft.Extensions.Hosting 8.0.0
or above is referenced - and yes, it works with .NET 6 applications too.
There is a new interface in the pacage, named IHostedLifecycleService
. Refer here for more details for the interface.
The key take away is that it provides more methods to be called during various steps in starting the host. One of them, StartingAsync
will be called after all the services are ready in the DI container, but before the host starts. That's exactly where we would usually want our one off initializing code to run.
Here's how to use it:
-
Refer to the package
Microsoft.Extensions.Hosting
;- You don't need to do this manually if you are running a .NET 8 application because its already there.
-
Create a class that implements
IHostedLifecycleService
. There are several methods to be implemented. Related to our goal isStartingAsync
, which runs before any of the regularIHostedService
. For example:namespace LearnHostedLifetimeService; public class MyHostedLifetimeService : IHostedLifecycleService { public Task StartAsync(CancellationToken cancellationToken) => Task.CompletedTask; public Task StartingAsync(CancellationToken cancellationToken) { Console.WriteLine("Starting async. This is expected to be called before {0}.", nameof(DemoRegularHostedService)); return Task.CompletedTask; } ... }
-
Optionally, we can add a regular
Background
service and check out the running sequence by ourselves:namespace LearnHostedLifetimeService; public class DemoRegularHostedService : BackgroundService { protected override Task ExecuteAsync(CancellationToken stoppingToken) { Console.WriteLine("Execution the {0}", nameof(DemoRegularHostedService)); return Task.CompletedTask; } }
-
Register the hosted lifecycle along with other hosted services:
builder.Services.AddHostedService<DemoRegularHostedService>(); // Although this is registered earlier, it still executes later. builder.Services.AddHostedService<MyHostedLifetimeService>(); // The StartingAsync will be called first.