Introduction: In this article, I will describe how ASP.NET Core 3.0 WebHost small change to make use IHostedService running asynchronous tasks more easily when the application starts.
A series exploring ASP.NET Core 3.0: new project file, Program.cs and generic host
Explore ASP.Net Core 3.0 Series II: talk ASP.Net Core 3.0 of Startup.cs
Explore ASP.Net Core 3.0 series three: ASP.Net Core 3.0 The Service provider validation
Explore ASP.Net Core 3.0 Series Six: ASP.NET Core 3.0 new features start structured log information
A running asynchronous tasks when the app starts
There are many reasons why you might want to do - for example, to run the database migration, verify strongly typed configuration or fill cache. Unfortunately, in 2.x is not possible to use any of the built-in ASP.NET Core primitives for this purpose:
- IStartupFilter a synchronous API, so we need to synchronize asynchronous.
- IApplicationLifetime a synchronous API, and trigger ApplicationStarted event after server start processing the request.
- IHostedService with asynchronous API, but after starting the implementation of server and begin processing requests.
Instead, I propose two possible solutions:
- Manual tasks before building WebHost but after running.
- Before starting the server receives the request, using a custom IServer realized when the server starts running tasks. Unfortunately, this approach may be problematic.
Use ASP.NET Core 3.0, the code of WebHost make small changes will make a big difference - we no longer need these solutions, and can be used IHostedService without fear!
In ASP.NET Core 2.x, you can achieve IHostedService service by running in the background. These soon (ie, after Kestrel Web server is started) start after the application starts to process the request, and stops when the application is closed.
In ASP.NET Core 3.0 in, IhostedService still have the same function - to run background tasks. However, due to a slight change WebHost, you can now also be used to run asynchronous tasks automatically when the application starts.
Change the following lines from ASP.NET Core 2.x in the WebHost:
public class WebHost { public virtual async Task StartAsync(CancellationToken cancellationToken = default) { // ... initial setup await Server.StartAsync(hostingApp, cancellationToken).ConfigureAwait(false); // Fire IApplicationLifetime.Started _applicationLifetime?.NotifyStarted(); // Fire IHostedService.Start await _hostedServiceExecutor.StartAsync(cancellationToken).ConfigureAwait(false); // ...remaining setup } }
Changing 3.0 ASP.Net Core follows:
public class WebHost { public virtual async Task StartAsync(CancellationToken cancellationToken = default) { // ... initial setup // Fire IHostedService.Start await _hostedServiceExecutor.StartAsync(cancellationToken).ConfigureAwait(false); // ... more setup await Server.StartAsync(hostingApp, cancellationToken).ConfigureAwait(false); // Fire IApplicationLifetime.Started _applicationLifetime?.NotifyStarted(); // ...remaining setup } }
As you can see, IHostedService.Start now performed before Server.StartAsync. This change means that you can now use IHostedService running asynchronous tasks.
Suppose you want to delay application processing requests until asynchronous tasks completed. If this is not the case, you might want to use the health check method final article in this series of articles.
Second, the use IHostedService a running asynchronous tasks when the app starts
We can create a task by implementing IHostedService, this interface contains two methods:
public interface IHostedService { Task StartAsync(CancellationToken cancellationToken); Task StopAsync(CancellationToken cancellationToken); }
Any code you want to run prior to receiving the request should be placed StartAsync method. In this case, you can ignore StopAsync method.
For example, the following task to start when the application starts to run asynchronously EF Core migration:
public class MigratorHostedService: IHostedService { // We need to inject the IServiceProvider so we can create // the scoped service, MyDbContext private readonly IServiceProvider _serviceProvider; public MigratorHostedService(IServiceProvider serviceProvider) { _serviceProvider = serviceProvider; } public async Task StartAsync(CancellationToken cancellationToken) { // Create a new scope to retrieve scoped services using(var scope = _serviceProvider.CreateScope()) { // Get the DbContext instance var myDbContext = scope.ServiceProvider.GetRequiredService<MyDbContext>(); //Do the migration asynchronously await myDbContext.Database.MigrateAsync(); } } // noop public Task StopAsync(CancellationToken cancellationToken) => Task.CompletedTask; }
To add to the task dependency injection vessel, and allowed to run before the application starts receiving the request, use AddHostedService <> extension method:
public class Startup { public void ConfigureServices(IServiceCollection services) { // other DI configuration services.AddHostedService<MigratorHostedService>(); } public void Configure(IApplicationBuilder) { // ...middleware configuration } }
These services will be added to the order of execution in accordance with the DI container, that is later added to the ConfigureServices the service will be performed at startup after startup.
Third, the summary
In this article, I described the minor changes in ASP.NET Core 3.0 WebHost how to enable you to run asynchronous tasks more easily when the application starts. In ASP.NET Core 2.x, it is not an ideal option, but the change means that you can use 3.0 IHostedService to fulfill that role.
Translation: Andrew Lock https://andrewlock.net/running-async-tasks-on-app-startup-in-asp-net-core-3/
Author: Guo Zheng
Source: http: //www.cnblogs.com/runningsmallguo/
This article belongs to the author and blog Park total, welcome to reprint, but without the author's consent declared by this section must be retained, and given the original article page link in the apparent position.