Understanding BackgroundTasks in .Net 8 C#

Valentyn Osidach 📚
.Net Programming
Published in
3 min readAug 26, 2024

Understanding BackgroundTasks

Background tasks in .NET are typically used for operations that need to run without blocking the main thread, ensuring the application remains responsive. In .NET 8, the infrastructure for handling background tasks has been refined to provide better performance, resource management, and simplicity in implementation.

Setting Up a Background Task

You generally use the interface to create a background task in .NET 8. This interface provides a straightforward way to manage long-running tasks that start when the application starts and stop when the application stops.

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

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

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

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Background task starting.");

while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Background task doing work.");
//Your code here ...
await Task.Delay(1000, stoppingToken);
}

_logger.LogInformation("Background task stopping.");
}
}

In this example:

  • MyBackgroundService inherits from BackgroundService, a base class provided by .NET for implementing background tasks.
  • The ExecuteAsync method is where the background work is performed. It runs in a loop until the application is stopped or a cancellation token is triggered.
  • The Task.Delay(1000) simulates a task running every second.

Registering the Background Service

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddHostedService<MyBackgroundService>();

Advanced Scenarios with BackgroundTasks

  • Scoped Services: If your background task needs to interact with services registered with a scoped lifetime, you can create a scope inside your task.
  • Periodic Tasks: You can leverage timers or scheduling libraries for tasks that need to run at regular intervals.
  • Concurrency: If your task involves parallel operations, ensure proper concurrency management to avoid issues like race conditions.

Background Task with Scoped Services

using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Threading;
using System.Threading.Tasks;

public class ScopedBackgroundService : BackgroundService
{
private readonly IServiceProvider _serviceProvider;
private readonly ILogger<ScopedBackgroundService> _logger;

public ScopedBackgroundService(IServiceProvider serviceProvider, ILogger<ScopedBackgroundService> logger)
{
_serviceProvider = serviceProvider;
_logger = logger;
}

protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("Scoped Background Service is starting.");

while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Scoped Background Service is doing background work.");

// Create a new scope
using (var scope = _serviceProvider.CreateScope())
{
//Your service
var scopedProcessingService = scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();

await scopedProcessingService.DoWork(stoppingToken);
}

await Task.Delay(5000, stoppingToken); // Simulate some delay between work cycles
}

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

Registering the Background Service

var builder = WebApplication.CreateBuilder(args);
var services = builder.Services;

services.AddHostedService<MyBackgroundService>();
services.AddScoped<IScopedProcessingService, ScopedProcessingService>();

Explanation of the Implementation

  • Scoped Service: ScopedProcessingService is a service with a scoped lifetime, meaning its instance is tied to the lifespan of a specific request or operation.
  • Background Service: ScopedBackgroundService inherits from BackgroundService and is designed to run continuously while the application is running.
  • Creating a Scope: Inside the ExecuteAsync method of the background service, a new scope is created using _serviceProvider.CreateScope(). This scope allows the background service to resolve and use the ScopedProcessingService.
  • Task Execution: The scoped service (ScopedProcessingService) performs its work inside this scope, ensuring that all dependencies with scoped lifetimes are disposed of properly when the scope ends.

Conclusion

Background tasks are a powerful feature in .NET 8, enabling developers to offload time-consuming or repetitive tasks from the main application thread. With proper implementation, these tasks can enhance the responsiveness and scalability of your applications. By following best practices around registration, graceful shutdowns, and monitoring, you can ensure that your background tasks are reliable and performant.

Whether you’re building a web application, an API, or a microservice, leveraging background tasks can be a game-changer in handling asynchronous operations efficiently.

Microsoft Learn Background tasks

--

--

Valentyn Osidach 📚
.Net Programming

I am a software developer from Ukraine with more than 7 years of experience. I specialize in C# and .NET and love sharing my development knowledge. 👨🏻‍💻