.Net Core 2.1 > Nouveauté – BackgroundService (IHostedService)

.Net Core 2.1 > Nouveauté – BackgroundService (IHostedService)

2018-07-03 0 By Nordes

Peut-être vous en avez entendu parlé, ou peut-être pas. Personnellement, je suis tombé sur l’article MSDN par hasard lors d’une recherche sur un autre sujet. Mais qu’est-ce que ça représente au fait, et qu’est-ce que ça ajoute cette nouveauté qui est proposé avec .Net Core 2.1? C’est simple, ça vous permet de pouvoir créer des services qui s’exécute en arrière plan! (Yahoo!)

Mais pourquoi c’est bon à savoir?

Par exemple, si vous avez une application WebAPI (backend) et que vous voulez effectuer un renouvellement de cache périodique aux 10 minutes, au lieu de lancer une CRON qui appellerait une API sur votre service pour le faire. C’est bien, mais si vous ne pouvez pas avoir de CRON et que vous ne voulez pas exposer un EndPoint de votre API, vous êtes mal barré. Vous devez attendre qu’un utilisateur se connecte à votre site afin de lancer la recharge de cache. Ceci sera lent et pourra vous causer plus de soucis que d’autre chose.

D’autre personne pourrait utiliser ce feature tout simplement pour faire un health check de votre services et de ses dépendances.

Comment ça marche?

C’est simple, vous implémenter la classe abstraite BackgroundService qui elle même hérite des interfaces IHostedService & IDisposable. Du coup vous n’avez qu’à implémenter la partie du déclenchement du service ExecuteAsync(CancellationToken stoppingToken). Notez, que vous pouvez aussi libérer vos ressources lors de la disposition de votre application (I.E. fin d’exécution). Dans ce cas, vous devrez override la méthode StopAsync.

Mais que mettre dans l’exécution asynchrone vous me direz? Dans le cas où vous voulez vérifier aux 10 minutes votre cache, je vous dirais de mettre tout simplement une boucle semi-infinie (utilisation du token d’annulation est là pour ça) qui invalidera et rebâtira au besoin votre cache (Exemple).

Voici un exemple d’implémentation (Classe de BgService):

public class CleanCacheBackgroundService : BackgroundService {
  private readonly ILogger<CleanCacheBackgroundService> _logger;
  private readonly IOtherDependency _otherDependency;

  public CleanCacheBackgroundService(ILogger<CleanCacheBackgroundService> logger, IOtherDependency otherDependency) {
    _logger = logger;
    _otherDependency = otherDependency;
  }

  protected override async Task ExecuteAsync(CancellationToken stoppingToken) {
    _logger.LogDebug($"CleanCacheBackgroundService va démarrer.");
    stoppingToken.Register(() => _logger.LogDebug($"CleanCacheBackgroundService va s'arrêter."));
    while (!stoppingToken.IsCancellationRequested) {
       _logger.LogDebug($"CleanCache : La tâche de nettoyage vient de débuter.");

       otherDependency.CleanCache();

       // Attendre... jusqu'à la nouvelle exécution
       await Task.Delay(otherDependency.DelayBeforeCleaningAgain, stoppingToken).ConfigureAwait(false);
    }
  }

  protected override async Task StopAsync (CancellationToken stoppingToken) {
    // Mettre vos disposition de resource ici. C'est appelé lors de la disposition de votre object.
  }
}

Ensuite, afin que ça démarre au début de votre application, vous n’aurez qu’à enregistrer dans vos dépendances le service d’arrière plan.

// Startup.cs dans la majorité des cas.

public IServiceProvider ConfigureServices(IServiceCollection services)
{            
    // Autre injections (DI)

    // Enregistrement des tâches d'arrière plan.
    services.AddSingleton<IHostedService, CleanCacheBackgroundService>();

    //...
}

Lorsque vous allez démarrer votre application, vos services démarrerons aussi au même moment ;). Ça rest beaucoup plus clean que d’ajouter des démarrage à la mitaine.

CQFD ;P