2

我正在创建一个将作为 Windows 服务运行的工作服务。我有一个要求,我想调用两个可能具有不同计时器的任务。

SayDoWork应该每 5 分钟调用一次,并且DoAnotherWork应该每 10 分钟左右调用一次。这两个任务可以并行运行,互不依赖。

我能够创建DoWork每 5 分钟运行一次的任务。我对如何实现另一个具有不同计时器持续时间的任务感到有点困惑?

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

2 回答 2

7

这两个任务可以并行运行,互不依赖。

在我看来,您有两项服务:

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
    }
  }
}

我还修改了IDataLoaderService使用的方式,使其不在其范围之外使用,并将Task.Delay参数更改为更不言自明。

于 2020-07-21T03:21:27.127 回答
0

如果您不想在您的情况下使用现有的调度库,您可以使用两个计时器,就像在这个文档System.Threading.Timer使用的那样。像这样的东西:

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();
    }
}
于 2020-07-20T22:39:39.713 回答