Utiliser des services délimités dans un BackgroundService

Lorsque vous inscrivez des implémentations de l’utilisation IHostedService de l’une AddHostedService des méthodes d’extension, le service est inscrit en tant que singleton. Il peut y avoir des scénarios dans lesquels vous souhaitez vous appuyer sur un service délimité. Pour plus d’informations, consultez Injection de dépendances dans .NET : Durées de vie du service.

Dans ce tutoriel, vous allez apprendre à :

Conseil

Tout le code source d’exemple « Workers dans .NET » peut être téléchargé dans l’Explorateur d’exemples. Pour plus d’informations, consultez Parcourir les exemples de code : Workers dans .NET.

Prérequis

Création d'un projet

Pour créer un projet de service Worker avec Visual Studio, vous devez sélectionner Fichier>Nouveau>Projet.... Dans la boîte de dialogue Créer un projet, recherchez « Worker Service », puis sélectionnez Modèle Worker Service. Si vous préférez utiliser l’interface CLI .NET, ouvrez votre terminal favori dans un répertoire de travail. Exécutez la commande dotnet new et remplacez le <Project.Name> par le nom de projet souhaité.

dotnet new worker --name <Project.Name>

Pour plus d’informations sur la commande de projet de service new worker de l’interface CLI .NET, consultez dotnet new worker.

Conseil

Si vous utilisez Visual Studio Code, vous pouvez exécuter des commandes CLI .NET à partir du terminal intégré. Pour plus d’informations, consultez Visual Studio Code : terminal intégré.

Créer des services délimités

Pour utiliser des services délimités au sein d’un BackgroundService, créez une étendue. Par défaut, aucune étendue n’est créée pour un service hébergé. Le service en arrière-plan délimité contient la logique de la tâche en arrière-plan.

namespace App.ScopedService;

public interface IScopedProcessingService
{
    Task DoWorkAsync(CancellationToken stoppingToken);
}

L’interface précédente définit une méthode unique DoWorkAsync. Pour définir l’implémentation par défaut :

  • Le service est asynchrone. La méthode DoWorkAsync retourne un Task. À des fins de démonstration, un délai de dix secondes est attendu dans la DoWorkAsync méthode.
  • Une ILogger est injectée dans le service.:
namespace App.ScopedService;

public sealed class DefaultScopedProcessingService(
    ILogger<DefaultScopedProcessingService> logger) : IScopedProcessingService
{
    private int _executionCount;

    public async Task DoWorkAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            ++ _executionCount;

            logger.LogInformation(
                "{ServiceName} working, execution count: {Count}",
                nameof(DefaultScopedProcessingService),
                _executionCount);

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

Le service hébergé crée une étendue pour résoudre le service des tâches en arrière-plan délimitées pour appeler sa DoWorkAsyncméthode. DoWorkAsync retourne un Task, qui est attendu dans ExecuteAsync :

Réécrire la classe Worker

Remplacez la classe Worker existante par le code C# suivant et renommez le fichier ScopedBackgroundService.cs :

namespace App.ScopedService;

public sealed class ScopedBackgroundService(
    IServiceScopeFactory serviceScopeFactory,
    ILogger<ScopedBackgroundService> logger) : BackgroundService
{
    private const string ClassName = nameof(ScopedBackgroundService);

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation(
            "{Name} is running.", ClassName);

        await DoWorkAsync(stoppingToken);
    }

    private async Task DoWorkAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation(
            "{Name} is working.", ClassName);

        using (IServiceScope scope = serviceScopeFactory.CreateScope())
        {
            IScopedProcessingService scopedProcessingService =
                scope.ServiceProvider.GetRequiredService<IScopedProcessingService>();

            await scopedProcessingService.DoWorkAsync(stoppingToken);
        }
    }

    public override async Task StopAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation(
            "{Name} is stopping.", ClassName);

        await base.StopAsync(stoppingToken);
    }
}

Dans le code précédent, une étendue explicite est créée et l’implémentation de IScopedProcessingService est résolue depuis la fabrique d’étendue du service d’injection de dépendances. L’instance de service résolue est délimitée et sa DoWorkAsync méthode est attendue.

Remplacez le contenu du fichier modèle Program.cs par le code C# suivant :

using App.ScopedService;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<ScopedBackgroundService>();
builder.Services.AddScoped<IScopedProcessingService, DefaultScopedProcessingService>();

IHost host = builder.Build();
host.Run();

Les services sont inscrits dans (Program.cs). Le service hébergé est inscrit avec la méthode d’extension AddHostedService.

Pour plus d’informations sur l’inscription de services, consultez Injection de dépendances dans .NET.

Vérifier les fonctionnalités du service

Pour exécuter l’application à partir de Visual Studio, sélectionnez F5 ou sélectionnez l’option de menu Déboguer>Démarrer le débogage. Si vous utilisez l’interface CLI .NET, exécutez la commande dotnet run à partir du répertoire de travail :

dotnet run

Pour plus d’informations sur la commande d’exécution de l’interface CLI .NET, consultez dotnet run.

Laissez l’application s’exécuter un peu pour générer plusieurs incréments de nombre d’exécutions. Vous devez voir des informations semblables à ce qui suit :

info: App.ScopedService.ScopedBackgroundService[0]
      ScopedBackgroundService is running.
info: App.ScopedService.ScopedBackgroundService[0]
      ScopedBackgroundService is working.
info: App.ScopedService.DefaultScopedProcessingService[0]
      DefaultScopedProcessingService working, execution count: 1
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: .\scoped-service
info: App.ScopedService.DefaultScopedProcessingService[0]
      DefaultScopedProcessingService working, execution count: 2
info: App.ScopedService.DefaultScopedProcessingService[0]
      DefaultScopedProcessingService working, execution count: 3
info: App.ScopedService.DefaultScopedProcessingService[0]
      DefaultScopedProcessingService working, execution count: 4
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
info: App.ScopedService.ScopedBackgroundService[0]
      ScopedBackgroundService is stopping.

Si vous exécutez l’application à partir de Visual Studio, sélectionnez Déboguer>Arrêter le débogage.... Vous pouvez également sélectionner Ctrl + C dans la fenêtre de console pour signaler l’annulation.

Voir aussi