liveBook · Manning

IHostedService

As explained in ASP.NET Core in Action, 3e

IHostedService is a .NET interface for components that start and stop with an application host and perform managed background work.

IHostedService lets a .NET application run work in the background instead of making a user wait for it. An ASP.NET Core app can, for example, accept a request to send an email, return a response, and process the queued email separately. Hosted services start and stop with the application. section 34.1

public interface IHostedService
{
   Task StartAsync(CancellationToken cancellationToken);
   Task StopAsync(CancellationToken cancellationToken);
}

The interface has two lifecycle methods: StartAsync runs during application startup, and StopAsync runs as the application shuts down. section 34.1.1

StartAsync runs inline during startup. If it waits for a long-running task to finish, the application cannot finish starting. For work that should continue throughout the application’s lifetime, usually derive from BackgroundService instead. Override ExecuteAsync, do the work there, and use its CancellationToken to stop when shutdown begins. Waiting in StartAsync can still be useful when the app must complete a task before handling requests. section 34.1.1 section 34.4

Keep an exchange-rate endpoint fast

A hosted service can repeatedly fetch exchange rates from a remote API and update a shared cache. The endpoint reads the cache rather than making its own HTTP call. Register the typed client, register the cache as a singleton, and add the background task with AddHostedService<ExchangeRatesHostedService>(). If the first update must succeed before requests begin, StartAsync can deliberately wait for it. section 34.1.1

Listing 34.3 Registering an IHostedService with the DI container
WebApplicationBuilder builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpClient<ExchangeRatesClient>();             #1
builder.Services.AddSingleton<ExchangeRatesCache>();               #2
builder.Services.AddHostedService<ExchangeRatesHostedService>();   #3
#1 Registers the typed client as before
#2 Adds the cache object as a singleton so it is shared throughout your app
#3 Registers ExchangeRatesHostedService as an IHostedService

This registration listing shows the typed HTTP client, shared singleton cache, and hosted service added to the dependency-injection container. section 34.1.1

A hosted service is created once, so do not constructor-inject a scoped dependency into it. If each update needs a scoped service such as an EF Core DbContext, call IServiceProvider.CreateScope(), resolve the dependency from that scope, and dispose the scope when the update finishes. Unlike an HTTP request, a background task has no automatically created request scope. section 34.1.2

The same interface also supports headless worker services built with the generic IHost when no HTTP endpoint is needed. For more elaborate schedules, Quartz.NET can run its scheduler as an IHostedService; a basic hosted service need not take on that scheduling machinery. section 34.2 section 34.3

How ASP.NET Core in Action, 3e covers it

How deep it goes
Defines both lifecycle methods and works through BackgroundService startup, shutdown, registration, and scoped dependencies; leaves advanced scheduling to Quartz.NET.
Examples
Uses an exchange-rate cache refreshed from a remote API, plus a database variation requiring an EF Core DbContext scope.
What it assumes
Introduces the hosted-service lifecycle while drawing on dependency-injection lifetimes and a previously registered typed HTTP client.
What you can do after
Build it from scratch with BackgroundService and AddHostedService<T>(), then manage shutdown and scoped dependencies safely.
How it connects
Connects BackgroundService, dependency-injection scopes, CancellationToken, worker services, generic IHost, and Quartz.NET scheduling.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of ASP.NET Core in Action, 3e. The section links point to the parts of the book it draws on.