Building Background Services with IHostedService in .NET

Background services are long-running processes that operate independently of the main application flow. They perform tasks in the background without blocking user interactions or requiring immediate responses. Background services are essential for handling tasks such as processing queues, sending notifications, or performing scheduled maintenance.

One of the most powerful and flexible ways to implement background services in .NET is by using the IHostedService interface. In this article, we’ll explore what IHostedService is, how it works, and how you can use it effectively in your .NET applications.

What is IHostedService?

IHostedService is an interface in the Microsoft.Extensions.Hosting namespace that allows you to create background tasks that run alongside your application.

The interface defines two primary methods:

  • StartAsync(CancellationToken): Called when the host starts, allowing the service to initialize and begin its work.
  • StopAsync(CancellationToken): Called when the host is shutting down, enabling graceful cleanup.

Additionally, .NET 6 introduced BackgroundService, an abstract base class that simplifies implementing IHostedService by providing a template for executing background tasks. I will use BackgroundService abstract class in the example below.

Why Use IHostedService?

Using IHostedService in your .NET application offers several benefits:

  1. Integration with the Host Lifecycle: IHostedService integrates directly with the application’s host (IHost or WebHost), enabling services to start automatically when the app starts and shut down gracefully when the app stops. This makes it ideal for background services that need to follow the application’s lifecycle without manual management.
  2. Dependency Injection Support: Services implementing IHostedService are registered in the dependency injection (DI) container and can receive dependencies via constructor injection. This makes it easy to use services such as ILogger<T>, IConfiguration, DbContext, or any other registered service, promoting clean, testable, and maintainable code.
  3. Graceful Shutdown: The StopAsync method provides a hook for gracefully releasing resources, completing background operations, or saving the current state before the application shuts down. This is especially important for long-running tasks or services that interact with external systems like databases or APIs.
  4. Scalability: IHostedService is ideal for implementing scalable, decoupled background workloads such as, Processing message queues, Running scheduled jobs, Monitoring system health etc.

Other than the benefits we’ve already covered, IHostedService offers additional advantages that make development easier. It helps organize your code by keeping background tasks separate from your main program logic. This separation makes your application cleaner and simpler to test, since each component focuses on a specific job.

Another advantage is its consistency across different application types. Whether you’re working on a web application, background service, or console program, IHostedService provides the same reliable way to handle background tasks. You can use the same approach in all your .NET projects without needing to learn different methods for each one.

Implementing a Background Service

Now that we understand IHostedService, let’s implement a background service using an example.

In this example, we’ll create a service that pings Google’s DNS server (8.8.8.8) to check its health status (whether it’s up and running).

Step 1: Create a New Project

We begin by setting up a new .NET console application. While we could implement background services in web apps or worker services, a console application provides the simplest environment to focus on the core functionality without additional complexity. The same principles apply regardless of project type, making this approach versatile for learning and experimentation.

First, ensure you have .NET installed by running:

dotnet --version

If you don’t have it, download it from dotnet.microsoft.com. For this demo, I’m using .NET 9.0.2, but the steps apply to any .NET version starting from 5.0.

Next, create a new console application:

dotnet new console -n GoogleDnsStatus.Demo

Step 2: Install Required Packages

The Microsoft.Extensions.Hosting package is essential as it provides the foundation for running hosted services in .NET. This package brings in necessary components like dependency injection and application lifecycle management, which are crucial for building background services. Without it, we’d have to manually handle service startup and shutdown, making our code more complex.

dotnet add package Microsoft.Extensions.Hosting

if you want to install a specific version of this package then you can define the version number using the –version flag

dotnet add package Microsoft.Extensions.Hosting --version 9.0.0

Step 3: Implement the Background Service

Our GooglePingService demonstrates several important concepts in background service implementation. By inheriting from BackgroundService instead of implementing IHostedService directly, we get a cleaner abstraction for long-running tasks. The service includes proper logging through ILogger, which is important since background services typically run unattended. We carefully handle cancellation requests to ensure graceful shutdowns, and include error handling to prevent the service from crashing due to temporary network issues.

GooglePingService.cs:

public class GooglePingService(ILogger<GooglePingService> logger) : BackgroundService
{
    private readonly string _targetHost = "8.8.8.8";

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation("Starting ping service for {Host}", _targetHost);

        using var ping = new Ping();

        while (!stoppingToken.IsCancellationRequested)
        {
            try
            {
                var reply = await ping.SendPingAsync(_targetHost, 2000);
                if (reply.Status == IPStatus.Success)
                    logger.LogInformation("Ping successful (Roundtrip: {Time}ms)", reply.RoundtripTime);
                else
                    logger.LogWarning("Ping failed: {Status}", reply.Status);
            }
            catch (Exception ex)
            {
                logger.LogError(ex, "Ping error");
            }

            await Task.Delay(10_000, stoppingToken);
        }
    }
}

Step 4: Configure the Host (Program.cs)

The host configuration is where we bring everything together. We set up console logging for visibility during development and testing, though in production you might configure more sophisticated logging solutions. Registering our service with AddHostedService ensures it starts automatically with the application. The host’s RunAsync method then manages the entire lifecycle, including proper startup and shutdown sequences.

Program.cs:

var builder = Host.CreateDefaultBuilder(args)
    .ConfigureLogging(logging =>
    {
        logging.ClearProviders();
        logging.AddConsole();
    })
    .ConfigureServices(services =>
    {
        services.AddHostedService<GooglePingService>();
    });

await builder.Build().RunAsync();

Testing the Background Service

Now that we’ve implemented our background service, let’s verify it works correctly. Testing is important because background services run independently, and we need to confirm they behave as expected during both normal operation and shutdown.

How to Run and Test the Service

1 – Start the Application: Open a terminal in your project directory and run:

dotnet run

You should immediately see logging output indicating the service has started. This is what I see as soon as I run this command.

Application startup messages

The service will ping Google’s DNS every 10 seconds. After waiting some time I start seeing more the ping responses.

Application ping messages

2 – Test Error Handling. To simulate network issues you can either temporarily disconnect your internet or block ICMP (ping) requests in your firewall. I disconnected my network and started seeing the messages below

Warning messages after I disconnected wifi

Final Thoughts

Implementing background services with IHostedService and BackgroundService provides a clean, reliable way to handle long-running tasks in .NET. By following this structured approach, setting up the project, implementing the service logic, configuring the host, and thoroughly testing, you can build background processes that easily integrate with your application’s lifecycle.

Whether you’re monitoring services, processing queues, or running scheduled jobs, this pattern ensures your tasks run efficiently and shut down gracefully. Now that you’ve seen it in action, you’re ready to apply these concepts to your own projects!


Enjoyed this post? Subscribe to my YouTube channel for more great content. Your support is much appreciated. Thank you!


Check out my Udemy profile for more great content and exclusive learning resources! Thank you for your support.
Ervis Trupja - Udemy



Enjoyed this blog post? Share it with your friends and help spread the word! Don't keep all this knowledge to yourself.

3 thoughts on “Building Background Services with IHostedService in .NET

Comments are closed.