Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Background Services (Tâches de fond)

Un serveur web ne sert pas uniquement à répondre à des requêtes HTTP. Parfois, il doit effectuer des tâches en arrière-plan (background tasks) de manière périodique ou continue.

Exemples :

  • Envoyer des emails en attente toutes les 5 minutes.
  • Nettoyer des fichiers temporaires toutes les heures.
  • Mettre à jour un classement (Leaderboard) en temps réel.
  • Écouter une file d’attente de messages (RabbitMQ, Azure Service Bus).

ASP.NET Core fournit une abstraction simple pour cela : les Hosted Services.

L’interface IHostedService

Tout service d’arrière-plan doit implémenter IHostedService.

public interface IHostedService
{
    Task StartAsync(CancellationToken cancellationToken);
    Task StopAsync(CancellationToken cancellationToken);
}

Cependant, il est plus simple d’hériter de la classe abstraite BackgroundService, qui gère déjà la mécanique de démarrage et d’arrêt.

Créer un Worker

Voici un exemple d’un service qui écrit “Hello” dans la console toutes les 5 secondes.

using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;

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

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

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        _logger.LogInformation("MyWorker démarré.");

        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker en cours d'exécution : {time}", DateTimeOffset.Now);

            // Attendre 5 secondes
            await Task.Delay(5000, stoppingToken);
        }
        
        _logger.LogInformation("MyWorker arrêté.");
    }
}

Points clés :

  1. ExecuteAsync : C’est la méthode principale. Elle doit tourner tant que l’application est en vie.
  2. while (!stoppingToken.IsCancellationRequested) : Cette boucle permet au service de continuer à tourner indéfiniment.
  3. stoppingToken : Ce token est annulé quand l’application s’arrête (ex: Ctrl+C). Il est important de le passer à Task.Delay pour que le service s’arrête proprement et immédiatement.

Enregistrement

Pour que le service démarre automatiquement avec l’application, il faut l’enregistrer dans Program.cs avec AddHostedService.

builder.Services.AddHostedService<MyWorker>();

Accéder aux Services (Scope)

Attention ! Les BackgroundService sont des Singletons. Vous ne pouvez pas injecter directement un service Scoped (comme votre DbContext ou vos Services métiers) dans le constructeur.

Si vous avez besoin d’accéder à la base de données, vous devez créer un scope manuellement.

public class LeaderboardUpdater : BackgroundService
{
    private readonly IServiceProvider _serviceProvider;

    public LeaderboardUpdater(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            // Création d'un scope manuel
            using (var scope = _serviceProvider.CreateScope())
            {
                // On récupère le service DEPUIS le scope
                var userService = scope.ServiceProvider.GetRequiredService<UserService>();
                
                // On peut maintenant utiliser le service
                await userService.UpdateLeaderboardAsync();
            }

            await Task.Delay(TimeSpan.FromMinutes(1), stoppingToken);
        }
    }
}