Asp.Net provides many ways to run background processes. They are:
- IHostedService interface
- BackgroundService abstract class
- Worker Service using Microsoft.NET.SDK.Worker
Actually they are just layers on top of each others, each layer provides extra functionality on the one below.
This post is going to describe each layer and what it provides.
Running background tasks using IHostedService
Asp.NET provides support for running background tasks in the same process that host Asp.net application.
By implementing IHostedService
interface, your background task will start a little bit after Asp.Net application start, and end when Asp.Net application shutdown.
P.S.: Asp.NET core server, Kestrel itself is a hosted service.
IHostedService has two methods:
public interface IHostedService
{
Task StartAsync(CancellationToken cancellationToken);
Task StopAsync(CancellationToken cancellationToken);
}
After you implement the interface, you need to register the task, and register it with the DI container. Asp.NET provides AddHostedService
extension method on IServiceCollection
for that purpose:
public void ConfigureServices(IServiceCollection services)
{
services.AddHostedService<MyExampleService>();
}
Using scoped services in the background task:
AddHostedService
is doing registering the service as Singleton in the DI container.
That leads to a problem if you need to use services registered as scoped-lifetime services.
To fix this problem, create a new container scope anywhere you need access to scoped service, as the following code:
public class MyExampleService : IHostedService
{
private readonly IServiceProvider _provider;
public MyExampleService (IServiceProvider provider)
{
_provider = provider;
}
public Task StartAsync (CancellationToken cancellationToken)
{
using (IServiceScope scope = _provider.CreateScope())
{
var scopedProvider = scope.ServiceProvider;
var client = scopeProvider.GetRequiredService<ExampleScopedService>();
...
}
}
}
Guidelines on IHostedService
There are subtleties to implementing the interface correctly. In particular, the StartAsync
method, although asynchronous, runs inline as part of your application startup. Background tasks that are expected to run for the lifetime of your application must return a Task immediately and schedule background work on a different thread. Calling await in the IHostedService.StartAsync
method will block your application from starting until the method completes. This can be useful in some cases, but it’s often not the desired behavior for background tasks.
BackgroundService
To make it easier to create background services using best-practice patterns, ASP.NET Core provides the abstract base class BackgroundService
, which implements IHostedService
and is designed to be used for long-running tasks. To create a background task you must override a single method of this class, ExecuteAsync
. You’re free to use async-await inside this method, and you can keep running the method for the lifetime of your app.
Worker Service
.NET provides a special kind of application called Worker Service
, which runs IHostedService in a host that is lighter than Asp.NET host.
That lighter host is Microsoft.Extensions.Hosting.Host
, which is a general host that is hosting the Asp.Net WebApplication itself.
I wrote before about the relation between Host and WebApplication.
The worker service's Host
will run background service, but doesn't handle HTTP request. It has the following:
- configuration features.
- logging features.
- dependency injection features.
To use Worker Service, run the following:
dotnet new worker
This will create a BackgroundService
class, that is hosted in Microsoft.Extensions.Hosting.Host
, which is an implementation of IHost
which what we described as a lightweight host.
Running Worker Service in production
You can run Worker Service as a Windows Service, or Linux's Systemd service.
Top comments (0)