web-dev-qa-db-fra.com

Comment exécuter BackgroundService sur un minuteur dans ASP.NET Core 2.1

Je veux exécuter un travail d'arrière-plan dans ASP.NET Core 2.1. Il doit fonctionner toutes les 2 heures et il devra accéder à mon conteneur DI car il effectuera des nettoyages dans la base de données. Il devra être async et il devrait fonctionner indépendamment de mon application ASP.NET Core 2.1.

J'ai vu qu'il y avait un IHostedService, mais ASP.NET Core 2.1 a également introduit une classe abstraite appelée BackgroundService qui fait un peu plus de travail pour moi. Cela semble bon, je veux l'utiliser!

Cependant, je n'ai pas pu comprendre comment exécuter un service dérivé de BackgroundService sur une minuterie.

Dois-je configurer cela dans la ExecuteAsync(token) en me souvenant de la dernière fois qu'il a fonctionné et en déterminant si cela a duré 2 heures, ou existe-t-il un moyen meilleur/plus propre de dire simplement quelque part qu'il doit fonctionner toutes les 2 heures?

De plus, mon approche de mon problème est-elle correcte avec un BackgroundService?

Je vous remercie!

Éditer:

Publié ceci sur le repo d'extensions MS

6
S. ten Brinke

@Panagiotis Kanavos a donné une réponse dans les commentaires de ma question mais il ne l'a pas publiée comme réponse réelle; cette réponse lui est dédiée.

J'ai utilisé un service d'arrière-plan chronométré comme celui des documents Microsoft pour créer le service.

internal class TimedHostedService : IHostedService, IDisposable
{
    private readonly ILogger _logger;
    private Timer _timer;

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

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is starting.");

        _timer = new Timer(DoWork, null, TimeSpan.Zero, 
            TimeSpan.FromSeconds(5));

        return Task.CompletedTask;
    }

    private void DoWork(object state)
    {
        _logger.LogInformation("Timed Background Service is working.");
    }

    public Task StopAsync(CancellationToken cancellationToken)
    {
        _logger.LogInformation("Timed Background Service is stopping.");

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

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer?.Dispose();
    }
}

Dans mon cas, j'ai fait l'appel asynchrone _timer En faisant new Timer(async () => await DoWorkAsync(), ...).

Dans le futur, une extension pourrait être écrite qui rendrait une classe comme celle-ci disponible dans le repo Extensions car je pense que c'est très utile. J'ai posté le lien du problème github dans la description.

Un conseil, si vous prévoyez de réutiliser cette classe pour plusieurs services hébergés, envisagez de créer une classe de base qui contient le minuteur et une PerformWork() abstraite ou quelque chose pour que la logique de "temps" ne soit qu'à un seul endroit.

Merci pour vos réponses! J'espère que cela aidera quelqu'un à l'avenir.

0
S. ten Brinke

Une façon d'y parvenir consiste à utiliser HangFire.io, cela gérera les tâches d'arrière-plan planifiées, gérera l'équilibrage entre les serveurs et est assez évolutif.

Voir Jobs récurrents sur https://www.hangfire.io

1
Mark Redman