In .NET (especially ASP.NET Core / Generic Host), both IHostedService and BackgroundService are used to run background tasks alongside your application. They’re part of the hosting infrastructure that manages app startup, lifetime, and graceful shutdown.
What is IHostedService?
IHostedService is a low-level interface that represents a background task.
It has two main methods:
• StartAsync(CancellationToken) → called when the app starts
• StopAsync(CancellationToken) → called when the app is shutting down
Why IHostedService exists?
It gives you full control over how your background process starts and stops.
Basic example
public class MyHostedService : IHostedService
{
public Task StartAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Service starting...");
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
Console.WriteLine("Service stopping...");
return Task.CompletedTask;
}
}
What is BackgroundService?
BackgroundService is an abstract base class that implements IHostedService for you.
Instead of dealing with StartAsync and StopAsync, you only implement:
ExecuteAsync(CancellationToken) → your long-running task
Why BackgroundService exists?
It simplifies writing continuous background work (loops, polling, workers).
Basic example
public class MyBackgroundWorker : BackgroundService
{
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while (!stoppingToken.IsCancellationRequested)
{
Console.WriteLine("Working...");
await Task.Delay(1000, stoppingToken);
}
}
}
How IHostedService and BackgroundService helps?
Both are used to:
• Run background jobs (timers, queues, polling APIs)
• Perform startup tasks (cache warming, migrations)
• Handle long-running processes
• Enable graceful shutdown with cancellation tokens
• Integrate with dependency injection and logging
When should you use each?
Use IHostedService when:
• You need fine control over start/stop lifecycle
• Your task is not continuous
• You manage your own threads/tasks manually
• You have multiple startup phases
Use BackgroundService when:
• You’re building a worker loop
• You need continuous processing
• You want cleaner, simpler code
• You rely on cancellation token for shutdown
Differences of IHostedService and BackgroundService
| Feature | IHostedService | BackgroundService |
|---|---|---|
| Type | Interface | Abstract class (implements IHostedService) |
| Methods to implement | StartAsync, StopAsync | ExecuteAsync |
| Complexity | More control, more boilerplate | Simpler, less boilerplate |
| Best for | Short-lived or controlled startup/shutdown tasks | Long-running background loops |
| Thread management | You manage it | Handled internally |
| Cancellation handling | Manual | Built-in via ExecuteAsync token |
| Readability | Lower | Higher |
| Typical usage | Initialization, one-time jobs | Polling, queue processing, workers |
Real-world examples
1. BackgroundService use cases
Queue consumer (RabbitMQ, Kafka)
Periodic API polling
Email sending worker
File processing pipeline
while (!stoppingToken.IsCancellationRequested)
{
var job = await queue.GetNextAsync();
await Process(job);
}
2. IHostedService use cases
Run database migration at startup
Warm up cache once
Initialize external connections
public async Task StartAsync(CancellationToken cancellationToken)
{
await database.MigrateAsync();
}
Alternatives
Depending on your needs, you might also consider:
1. Worker Services
• Template built on BackgroundService
• Good for microservices / daemons
2. Hangfire / Quartz.NET
• For scheduled jobs
• Persistent background processing
3. Azure Functions / WebJobs
• Event-driven background execution
4. Channels + Task.Run
• For lightweight in-process queues