What’s actually slowing this PC down?

Pick the symptom - the matching free tool is one click away.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

To run background work in an ASP.NET Core web app, register an IHostedService implementation with AddHostedService<T>() and let the app’s host manage its startup and shutdown. For a standalone background process, start with the Worker Service template instead. Use BackgroundService for a long-running loop, create dependency-injection scopes when the worker needs scoped services, and choose a timer or queue based on the work’s timing and ordering requirements.

Worker Service, hosted service, and BackgroundService: what is the difference?

These names describe related but different things. A Worker Service is a project template for creating a background-focused application. A hosted service is a service that implements IHostedService and participates in the Generic Host lifecycle. BackgroundService is a base class for a hosted service whose main work runs asynchronously over time. The host provides configuration, logging, dependency injection, and lifecycle management.

A Worker Service does not have to be an ASP.NET Core web application. Use it for a background-only executable; use an ASP.NET Core web project when the same process also serves HTTP endpoints.

Choose the project shape and register the worker

For a standalone background process

Create a Worker Service project with the .NET CLI:

dotnet new worker -o ContosoWorker

The template uses Microsoft.NET.Sdk.Worker and references Microsoft.Extensions.Hosting. The standard host setup registers the worker and runs the host:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
#1 Best Overall
Sale
Programming ASP.NET Core (Developer Reference)
  • Applying all key ASP.NET Core components, including MVC for HTML generation, .NET Core, EF Core, ASP.NET Identity, dependency injection, and more
  • Integrating ASP.NET Core with leading client-side frameworks, including Bootstrap
  • ASP.NET Core code for implementing business logic and data transformations
  • Handling configuration, routing, controllers, views, and common tasks (including posting forms and presenting data)
  • Performing complementary tasks: error handling, logging, application design, authentication, localization, and more
using Microsoft.Extensions.Hosting;

var builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<Worker>();

var host = builder.Build();
host.Run();

Microsoft describes the template as “a starting point for writing long running service apps.” See Background tasks with hosted services in ASP.NET Core and the .NET Worker Services overview.

For an existing ASP.NET Core web app

Register the background service in the web app’s existing host rather than creating a separate Worker Service project just to run the task:

builder.Services.AddHostedService<Worker>();

A web project uses Microsoft.NET.Sdk.Web and gets hosting support from the shared framework, so it generally does not need an explicit hosting-package reference. The web host also configures the HTTP server and request pipeline; the worker runs alongside that web workload.

Implement the service lifecycle

Use BackgroundService for a long-running loop

For work that continues until the application shuts down, derive from BackgroundService and override ExecuteAsync(CancellationToken). The returned task represents the service’s lifetime. Let the method become asynchronous promptly, and pass the stopping token to operations that support cancellation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
using Microsoft.Extensions.Hosting;

public sealed class Worker : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            await DoWorkAsync(stoppingToken);
            await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken);
        }
    }

    private static Task DoWorkAsync(CancellationToken cancellationToken)
    {
        // Perform one unit of work; pass the token to cancellable operations.
        return Task.CompletedTask;
    }
}

The example’s delay is illustrative; set the interval and work behavior to suit the application. Cancellation is a request to stop, not a guarantee that arbitrary in-flight work will finish safely. Decide how the application handles work already in progress, and design persistence, retries, and delivery guarantees according to the workload.

Implement IHostedService for explicit start and stop behavior

Implement IHostedService directly when the service needs explicit StartAsync and StopAsync methods, such as starting or releasing a resource. StartAsync runs before the request pipeline is configured and before the server starts. Hosted services start sequentially, so keep startup work short; a long synchronous initialization can delay the rest of the application. During graceful shutdown, use StopAsync to release resources as appropriate.

During shutdown, the host waits for background execution within its shutdown timeout. Microsoft’s hosted-services guidance documents a default cancellation timeout of 30 seconds and explains how to configure the limit. Do not assume a service can finish any amount of work before the host stops.

Use scoped dependencies inside a hosted service

A hosted service is not created once per HTTP request and does not automatically receive a new dependency-injection scope for each unit of background work. If it needs a scoped dependency, such as a data-access service, inject IServiceScopeFactory, create a scope for the operation, resolve the dependency from that scope, and dispose the scope when the operation ends.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

public sealed class Worker(IServiceScopeFactory scopeFactory) : BackgroundService
{
    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            await using var scope = scopeFactory.CreateAsyncScope();
            var processor = scope.ServiceProvider.GetRequiredService<IWorkProcessor>();
            await processor.ProcessAsync(stoppingToken);
        }
    }
}

This illustrative pattern creates a fresh scope for each iteration. For a queue consumer, create a scope per message or batch when that matches the unit of work. Check the API signatures against the target framework and the scoped service’s disposal requirements.

Choose a timer, awaited loop, or queue

Pattern Useful for Concurrency and durability
Timer callback Periodic polling or maintenance A timer does not wait for an earlier callback to finish, so callbacks can overlap when work takes longer than the interval. It is not a durable work queue.
Awaited delay loop Repeated work that should run one iteration at a time Awaiting each operation before the next delay naturally serializes iterations within that worker.
Queue consumer Application-owned work items that should be processed in sequence A bounded in-memory queue controls process memory pressure, but its contents are not persisted across a crash or restart.

Prevent overlapping periodic work

Microsoft’s timer example uses System.Threading.Timer, but its callbacks can overlap if an earlier invocation has not completed when the next tick occurs. If overlap is unsafe, enforce mutual exclusion deliberately or use an awaited loop that waits for each operation to finish before starting another.

Use a queue when work arrives as separate items

A queue separates the code that submits work from the hosted service that processes it. Microsoft’s queue tutorial uses Channel<T> with bounded capacity and a hosted consumer that awaits items sequentially. This can help control concurrency and memory use inside one process, but it does not make queued work durable. If messages must survive process failure or coordinate across multiple instances, use an external durable broker and design the required persistence and retry behavior.

See Microsoft’s Create a Queue Service tutorial for a Channel-based worker pattern.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
Best Value
ASP.NET AJAX Programmer's Reference with ASP.NET 2.0 or SAP.NET 3.5
  • New
  • Mint Condition
  • Dispatch same day for order received before 12 noon
  • Guaranteed packaging
  • No quibbles returns
Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Run the application as a Windows Service

When deploying to Windows without IIS, Microsoft’s Windows Service integration provides Windows-specific lifetime behavior for an ASP.NET Core application. Add the Microsoft.Extensions.Hosting.WindowsServices package and call UseWindowsService() on the host builder. When running as a Windows Service, the integration sets the content root to the application base directory and enables Event Log integration subject to documented defaults and permissions.

Choose the SDK according to the application’s role: Microsoft.NET.Sdk.Worker for a background-only process, or Microsoft.NET.Sdk.Web when the application also serves HTTP endpoints. Avoid relying on a Windows Service’s current working directory to locate files; use an appropriate application-base or absolute path. Follow the current Microsoft Windows Service hosting guidance for deployment details.

How to choose the right pattern

  • Background work only: Start with dotnet new worker and the Generic Host.
  • Background work plus HTTP endpoints: Register a hosted service in the ASP.NET Core web app’s host.
  • One continuous asynchronous task: Use BackgroundService and make its execution responsive to cancellation.
  • Explicit resource startup and shutdown: Implement IHostedService directly.
  • Periodic work: Use a timer only if overlap is acceptable or prevented; otherwise use a serialized awaited loop.
  • Discrete in-process work items: Use a queue consumer, with bounded capacity when memory pressure matters.
  • Work that must survive restarts or be shared across instances: Choose a durable external queue rather than relying on an in-memory Channel.
  • Windows Service deployment: Add Windows Services integration and use paths that do not depend on the process current directory.

The lifecycle and queue examples are documented in Microsoft’s hosted-services guide; host construction for web and worker applications is covered in .NET Generic Host in ASP.NET Core. Verify framework selectors and package versions for the target .NET release before using version-sensitive APIs.

Quick Recap

SaleBestseller No. 1
Programming ASP.NET Core (Developer Reference)
Programming ASP.NET Core (Developer Reference)
Integrating ASP.NET Core with leading client-side frameworks, including Bootstrap; ASP.NET Core code for implementing business logic and data transformations
$24.99
Bestseller No. 3
Bestseller No. 4
Bestseller No. 5
ASP.NET AJAX Programmer's Reference with ASP.NET 2.0 or SAP.NET 3.5
ASP.NET AJAX Programmer's Reference with ASP.NET 2.0 or SAP.NET 3.5
New; Mint Condition; Dispatch same day for order received before 12 noon; Guaranteed packaging
$56.00

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.