Search code examples
c#.net-coreasp.net-core-hosted-services

How to run multiple task in background service in .net core with different timer duration


I am creating a worker service which will be run as a windows service. I have a requirement where I would like to invoke two tasks which may have different timers.

Say DoWork should be called every 5 minutes and DoAnotherWork should be called every 10 minutes or so. These two tasks can run in parallel and are not dependant on each other.

I was able to create task DoWork which can run after every 5 minutes. I am a bit confused about how to implement another task that will have different timer duration?

public class Worker : BackgroundService
{        
    private readonly IServiceScopeFactory _scopeFactory;        
    private IDataLoaderService _dataLoaderService;        

    public override Task StartAsync(CancellationToken cancellationToken)
    {
        using var scope = _scopeFactory.CreateScope();
        _dataLoaderService = scope.ServiceProvider.GetRequiredService<IDataLoaderService>();                        
        return base.StartAsync(cancellationToken);
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {            
        while (!stoppingToken.IsCancellationRequested)
        {
            await DoWork(stoppingToken, _dataLoaderService);
            await Task.Delay(300000, stoppingToken); //Run every 5 minutes

            await DoAnotherWork(stoppingToken, _dataLoaderService);
            await Task.Delay(600000, stoppingToken); //Run every 10 minutes
        }
    }

    private async Task DoWork(CancellationToken stoppingToken, IDataLoaderService loaderService)
    {
        await loaderService.Process();            
    }        
    
    private async Task DoAnotherWork(CancellationToken stoppingToken, IDataLoaderService loaderService)
    {
        await loaderService.Validate();            
    }
}

Solution

  • These two tasks can run in parallel and are not dependant on each other.

    Sounds to me like you have two services:

    public class ProcessDataLoaderWorker : BackgroundService
    {
      private readonly IServiceScopeFactory _scopeFactory;
    
      protected override async Task ExecuteAsync(CancellationToken stoppingToken)
      {
        using var scope = _scopeFactory.CreateScope();
        var dataLoaderService = scope.ServiceProvider.GetRequiredService<IDataLoaderService>();
    
        while (true)
        {
          await dataLoaderService.Process();
          await Task.Delay(TimeSpan.FromMinutes(5), stoppingToken); //Run every 5 minutes
        }
      }
    }
    
    public class ValidateDataLoaderWorker : BackgroundService
    {
      private readonly IServiceScopeFactory _scopeFactory;
    
      protected override async Task ExecuteAsync(CancellationToken stoppingToken)
      {
        using var scope = _scopeFactory.CreateScope();
        var dataLoaderService = scope.ServiceProvider.GetRequiredService<IDataLoaderService>();
    
        while (true)
        {
          await dataLoaderService.Validate();
          await Task.Delay(TimeSpan.FromMinutes(10), stoppingToken); //Run every 10 minutes
        }
      }
    }
    

    I also modified the way the IDataLoaderService was used so that it is not used outside its scope, and changed the Task.Delay arguments to be more self-explanatory.