Background Services in .NET: Complete Guide with ASP.NET Core Examples
Many applications need to perform work in the background without waiting for user requests. Examples include sending emails, processing queues, generating reports, cleaning old data, and synchronizing information from external systems.
.NET provides Background Services that allow applications to execute long-running tasks while the application continues serving users. In this guide, you'll learn how Background Services work, when to use them, and how to implement them in ASP.NET Core.
- What are Background Services?
- IHostedService
- BackgroundService
- Scheduled tasks
- Dependency Injection
- Worker Services
- Best practices
What Is a Background Service?
A Background Service is a process that runs independently of incoming HTTP requests. It performs work behind the scenes while your application continues handling users and API calls.
Common examples include:
- Sending email notifications
- Processing message queues
- Generating reports
- Data synchronization
- Cache refresh operations
- Scheduled maintenance tasks
Understanding IHostedService
The foundation of background processing in ASP.NET Core is the
IHostedService interface.
It provides two methods:
StartAsync()StopAsync()
These methods are called when the application starts and stops.
public class MyHostedService : IHostedService
{
public Task StartAsync(
CancellationToken cancellationToken)
{
Console.WriteLine("Service Started");
return Task.CompletedTask;
}
public Task StopAsync(
CancellationToken cancellationToken)
{
Console.WriteLine("Service Stopped");
return Task.CompletedTask;
}
}
Registering a Hosted Service
Register the service in Program.cs.
builder.Services.AddHostedService<MyHostedService>();
The framework automatically starts and stops the service during the application lifecycle.
Using BackgroundService
In most situations, inheriting from BackgroundService
is simpler than implementing IHostedService manually.
BackgroundService provides an abstract method called
ExecuteAsync().
public class Worker : BackgroundService
{
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
Console.WriteLine("Running...");
await Task.Delay(
TimeSpan.FromSeconds(5),
stoppingToken);
}
}
}
This loop continues running until the application shuts down.
Creating Scheduled Tasks
Background Services are often used for scheduled jobs.
For example, sending a report every hour.
public class ReportService : BackgroundService
{
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await GenerateReport();
await Task.Delay(
TimeSpan.FromHours(1),
stoppingToken);
}
}
private Task GenerateReport()
{
Console.WriteLine("Generating report...");
return Task.CompletedTask;
}
}
Using Dependency Injection
Background Services support Dependency Injection just like controllers and other ASP.NET Core components.
public class EmailWorker : BackgroundService
{
private readonly IEmailService _emailService;
public EmailWorker(
IEmailService emailService)
{
_emailService = emailService;
}
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
await _emailService.SendPendingEmails();
await Task.Delay(
60000,
stoppingToken);
}
}
}
This approach keeps code clean and maintainable.
Using Scoped Services
Sometimes background workers need access to scoped services such as Entity Framework Core DbContext.
public class CleanupWorker : BackgroundService
{
private readonly IServiceScopeFactory _scopeFactory;
public CleanupWorker(
IServiceScopeFactory scopeFactory)
{
_scopeFactory = scopeFactory;
}
protected override async Task ExecuteAsync(
CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
using var scope =
_scopeFactory.CreateScope();
var db =
scope.ServiceProvider
.GetRequiredService<AppDbContext>();
// Database operations here
await Task.Delay(
TimeSpan.FromMinutes(30),
stoppingToken);
}
}
}
What Is a Worker Service?
A Worker Service is a .NET application template specifically designed for long-running background processes.
Unlike ASP.NET Core web applications, Worker Services do not serve web pages. Their primary purpose is background processing.
Common use cases include:
- Windows Services
- Linux Daemons
- Queue Processors
- Data Synchronization Services
- Monitoring Applications
Handling Exceptions
Background Services should always handle exceptions properly.
try
{
await ProcessJobs();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Unhandled exceptions can stop the service unexpectedly.
Performance Considerations
Background Services consume resources continuously while running.
To improve performance:
- Avoid tight loops.
- Use delays when appropriate.
- Release resources properly.
- Monitor memory usage.
- Use asynchronous operations.
Common Mistakes
- Ignoring cancellation tokens.
- Creating infinite loops without delays.
- Using DbContext directly without scopes.
- Not handling exceptions.
- Blocking async code.
Best Practices
- Prefer BackgroundService over IHostedService for most cases.
- Always respect cancellation tokens.
- Use Dependency Injection.
- Create scopes for scoped services.
- Log important events and errors.
- Keep background tasks focused and maintainable.
Frequently Asked Questions
What is the difference between IHostedService and BackgroundService?
BackgroundService is a helper class that implements IHostedService and simplifies long-running background work.
Can Background Services access a database?
Yes. They commonly use Entity Framework Core through dependency injection.
Do Background Services run continuously?
They can. Many services run until the application shuts down, while others execute on a schedule.
Can I use multiple Background Services?
Yes. ASP.NET Core supports registering multiple hosted services.
Related Tutorials
- Task.Run() Explained
- Thread vs Task in C#
- Async and Await in C#
- Dependency Injection in ASP.NET Core
- Using HttpClient in C#
- Entity Framework Core CRUD
Conclusion
Background Services are an essential feature of modern .NET applications. They allow applications to perform long-running work independently from user requests while maintaining responsiveness.
By understanding IHostedService, BackgroundService, dependency injection, and proper cancellation handling, developers can build reliable and scalable background processing solutions.
For most ASP.NET Core applications, inheriting from BackgroundService provides the simplest and most maintainable approach.