Understanding Background Services in .NET 8: IHostedService and BackgroundService
Tags: dotnetcore, aspdotnet, dotnet
Published: 2024-06-09 14:08:41

.NET 8 introduces powerful features for managing background tasks with `IHostedService` and `BackgroundService`. These services enable long-running operations, such as scheduled tasks, background processing, and periodic maintenance tasks, to be seamlessly integrated into your applications. This article explores these new features and provides practical examples to help you get started. You can find the source code for these examples on my [GitHub repository](https://github.com/mohamedtayel1980/DotNet8NewFeature/tree/main/DotNet8NewFeature/BackgroundingService).

#### What are Background Services?

Background services in .NET allow you to run tasks in the background independently of the main application thread. This is essential for tasks that need to run continuously or at regular intervals without blocking the main application flow.

#### `IHostedService` Interface

The `IHostedService` interface defines two methods:
- **`StartAsync(CancellationToken cancellationToken)`**: Called when the application host starts.
- **`StopAsync(CancellationToken cancellationToken)`**: Called when the application host is performing a graceful shutdown.

**Example of `IHostedService` Implementation**:

```csharp
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public class TimedHostedService : IHostedService, IDisposable
{
    private readonly ILogger<TimedHostedService> _logger;
    private Timer _timer;

    public TimedHostedService(ILogger<TimedHostedService> logger)
    {
        _logger = logger;
    }

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Hosted Service running.");

        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        _logger.LogInformation("Timed Hosted Service is working.");
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Hosted Service is stopping.");

        _timer?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}
```

#### `BackgroundService` Class

The `BackgroundService` class is an abstract base class that simplifies the implementation of background tasks. It provides a single method to override:
- **`ExecuteAsync(CancellationToken stoppingToken)`**: Contains the logic for the background task and runs until the application shuts down.

**Example of `BackgroundService` Implementation**:

```csharp
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

public class TimedBackgroundService : BackgroundService
{
    private readonly ILogger<TimedBackgroundService> _logger;

    public TimedBackgroundService(ILogger<TimedBackgroundService> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("Timed Background Service running.");

        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Timed Background Service is working.");
            await Task.Delay(TimeSpan.FromSeconds(5), stoppingToken);
        }

        _logger.LogInformation("Timed Background Service is stopping.");
    }
}
```

#### Practical Usage

To utilize these background services in your .NET application, you need to register them in your dependency injection container. This can be done in the `Program.cs` file.

**Registering Hosted Services**:

```csharp
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main(string[] args)
    {
        var host = Host.CreateDefaultBuilder(args)
            .ConfigureServices(services =>
            {
                services.AddHostedService<TimedHostedService>();
                services.AddHostedService<TimedBackgroundService>();
            })
            .Build();

        await host.RunAsync();
    }
}
```

### Key Differences

- **Level of Abstraction**:
  - **`IHostedService`**: Requires manual implementation of starting and stopping logic.
  - **`BackgroundService`**: Simplifies the implementation by providing a base class with a single method to override.

- **Use Cases**:
  - **`IHostedService`**: Suitable for more complex scenarios where you need fine-grained control over the service lifecycle.
  - **`BackgroundService`**: Ideal for simpler, long-running tasks that benefit from reduced boilerplate code.

### Conclusion

.NET 8's background services, through `IHostedService` and `BackgroundService`, offer a robust and flexible way to manage background tasks. By choosing the appropriate abstraction based on your needs, you can efficiently implement and manage long-running operations in your applications. These new features enhance the ability to create responsive, scalable, and maintainable .NET applications.

This guide provides the foundation you need to start integrating background services into your .NET applications. For more complex scenarios, consider exploring additional capabilities and configurations offered by the .NET hosting framework.