Forem

Ghassan Karwchan
Ghassan Karwchan

Posted on

Best way to run background services in ASP.NET.

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);
}
Enter fullscreen mode Exit fullscreen mode

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>();
}
Enter fullscreen mode Exit fullscreen mode

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>();
         ...
      }
    }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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.

Image of Timescale

🚀 pgai Vectorizer: SQLAlchemy and LiteLLM Make Vector Search Simple

We built pgai Vectorizer to simplify embedding management for AI applications—without needing a separate database or complex infrastructure. Since launch, developers have created over 3,000 vectorizers on Timescale Cloud, with many more self-hosted.

Read more

Top comments (0)

Sentry image

See why 4M developers consider Sentry, “not bad.”

Fixing code doesn’t have to be the worst part of your day. Learn how Sentry can help.

Learn more

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay