Partage via


Implémenter l’interface IHostedService

Lorsque vous avez besoin d’un contrôle fini au-delà de celui fourni BackgroundService, vous pouvez implémenter votre propre IHostedService. L’interface IHostedService est la base de tous les services de longue durée dans .NET. Les implémentations personnalisées sont enregistrées par la méthode d’extension AddHostedService<THostedService>(IServiceCollection).

Dans ce tutoriel, vous allez apprendre à :

  • Implémentez les interfaces IHostedService et IAsyncDisposable.
  • Créez un service basé sur un minuteur.
  • Inscrivez l’implémentation personnalisée avec l’injection de dépendances et la journalisation.

Conseil / Astuce

Tous les exemples de code source « Workers in .NET » sont disponibles dans l’Explorateur d’exemples pour le téléchargement. Pour plus d’informations, consultez les exemples de code pour Workers dans .NET.

Prerequisites

Créer 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 « Service Worker », puis sélectionnez modèle De service Worker. 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 <Project.Name> par le nom souhaité de votre projet.

dotnet new worker --name <Project.Name>

Pour plus d’informations sur la commande de création d'un nouveau projet de service worker de .NET CLI, consultez dotnet new worker.

Conseil / Astuce

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 un service de minuteur

Le service d’arrière-plan basé sur le minuteur utilise la System.Threading.Timer classe. Le minuteur déclenche la DoWork méthode. Le minuteur est désactivé sur IHostLifetime.StopAsync(CancellationToken) et supprimé quand le conteneur du service est supprimé sur IAsyncDisposable.DisposeAsync() :

Remplacez le contenu du Worker modèle par le code C# suivant, puis renommez le fichier en TimerService.cs :

namespace App.TimerHostedService;

public sealed class TimerService(ILogger<TimerService> logger) : IHostedService, IAsyncDisposable
{
    private readonly Task _completedTask = Task.CompletedTask;
    private int _executionCount = 0;
    private Timer? _timer;

    public Task StartAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation("{Service} is running.", nameof(TimerHostedService));
        _timer = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(5));

        return _completedTask;
    }

    private void DoWork(object? state)
    {
        int count = Interlocked.Increment(ref _executionCount);

        logger.LogInformation(
            "{Service} is working, execution count: {Count:#,0}",
            nameof(TimerHostedService),
            count);
    }

    public Task StopAsync(CancellationToken stoppingToken)
    {
        logger.LogInformation(
            "{Service} is stopping.", nameof(TimerHostedService));

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

        return _completedTask;
    }

    public async ValueTask DisposeAsync()
    {
        if (_timer is IAsyncDisposable timer)
        {
            await timer.DisposeAsync();
        }

        _timer = null;
    }
}

Important

Il Worker s’agissait d’une sous-classe de BackgroundService. À présent, TimerService implémente à la fois les interfaces IHostedService et IAsyncDisposable.

Il TimerService est sealed, et transmet l'appel DisposeAsync à partir de son instance _timer. Pour plus d’informations sur le « modèle de suppression en cascade », consultez la section Implémenter une DisposeAsync méthode.

Lorsqu’on appelle StartAsync, le minuteur est instancié, démarrant ainsi le minuteur.

Conseil / Astuce

Le Timer n’attend pas la fin des exécutions précédentes de DoWork pour finir, de sorte que l’approche indiquée peut ne pas convenir à tous les scénarios. Interlocked.Increment est utilisé pour incrémenter le compteur d’exécution en tant qu’opération atomique, ce qui garantit que plusieurs threads ne sont pas mis à jour _executionCount simultanément.

Remplacez le contenu existant Program par le code C# suivant :

using App.TimerHostedService;

HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Services.AddHostedService<TimerService>();

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

Le service est inscrit dans (Program.cs) avec la méthode d’extension AddHostedService . Il s’agit de la même méthode d’extension que vous utilisez lors de l’inscription de BackgroundService sous-classes, car elles implémentent l’interface IHostedService .

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

Vérifier la fonctionnalité de 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 dotnet run commande à 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 pour un peu pour générer plusieurs incréments de nombre d’exécutions. Vous verrez une sortie similaire à ce qui suit :

info: App.TimerHostedService.TimerService[0]
      TimerHostedService is running.
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: .\timer-service
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 1
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 2
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 3
info: App.TimerHostedService.TimerService[0]
      TimerHostedService is working, execution count: 4
info: Microsoft.Hosting.Lifetime[0]
      Application is shutting down...
info: App.TimerHostedService.TimerService[0]
      TimerHostedService 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

Il existe plusieurs didacticiels connexes à prendre en compte :