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

巧了我就是萌 提交于 2020-08-05 07:11:16

问题


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();            
    }
}

回答1:


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.




回答2:


If you don't want to use existing scheduling libraries in your case you can go with having two timers, like in this docs, where System.Threading.Timer is utilized. Something like that:

public class Worker : IHostedService, IDisposable
{        
    private readonly IServiceScopeFactory _scopeFactory;        
    private IDataLoaderService _dataLoaderService;  
    private Timer _timer1;
    private Timer _timer2;      

    public Task StartAsync(CancellationToken cancellationToken)
    {
        _dataLoaderService = scope.ServiceProvider.GetRequiredService<IDataLoaderService>();              
        _timer1 = new Timer(DoWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(300));
        _timer2 = new Timer(DoAnotherWork, null, TimeSpan.Zero, TimeSpan.FromSeconds(600));
        return Task.CompletedTask;
    }    
   
    private async void DoWork(object _)
    {
        // or create scope and resolve here
        await _loaderService.Process();            
    }        
    
    private async void DoAnotherWork(object _)
    {
        // or create scope and resolve here
        await _loaderService.Validate();            
    }

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

        _timer1?.Change(Timeout.Infinite, 0);
        _timer2?.Change(Timeout.Infinite, 0);

        return Task.CompletedTask;
    }

    public void Dispose()
    {
        _timer1?.Dispose();
        _timer2?.Dispose();
    }
}


来源:https://stackoverflow.com/questions/63004613/how-to-run-multiple-task-in-background-service-in-net-core-with-different-timer

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!