C# 如何在.net core的后台服务中以不同的计时器持续时间运行多个任务
我正在创建一个将作为windows服务运行的辅助服务。我需要调用两个可能有不同计时器的任务 SayC# 如何在.net core的后台服务中以不同的计时器持续时间运行多个任务,c#,.net-core,asp.net-core-hosted-services,C#,.net Core,Asp.net Core Hosted Services,我正在创建一个将作为windows服务运行的辅助服务。我需要调用两个可能有不同计时器的任务 Saydoork应该每5分钟调用一次,而DoAnotherWork应该每10分钟左右调用一次。这两个任务可以并行运行,并且互不依赖 我能够创建taskDoWork,每5分钟运行一次。对于如何实现另一个具有不同计时器持续时间的任务,我有点困惑 public class Worker : BackgroundService { private readonly IServiceScop
doork
应该每5分钟调用一次,而DoAnotherWork
应该每10分钟左右调用一次。这两个任务可以并行运行,并且互不依赖
我能够创建taskDoWork
,每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();
}
}
public class Worker:BackgroundService
{
专用读写器ViceScopeFactory\u scopeFactory;
专用IDataLoaderService(数据加载服务);;
公共覆盖任务StartAsync(CancellationToken CancellationToken)
{
使用var scope=_scopeFactory.CreateScope();
_dataLoaderService=scope.ServiceProvider.GetRequiredService();
返回base.StartAsync(cancellationToken);
}
受保护的覆盖异步任务ExecuteAsync(CancellationToken stoppingToken)
{
同时(!stoppingToken.IsCancellationRequested)
{
等待工作(停止停止,数据加载服务);
等待任务。延迟(300000,停止);//每5分钟运行一次
等待完成其他工作(停止通话,数据加载服务);
等待任务。延迟(600000,停止);//每10分钟运行一次
}
}
专用异步任务DoWork(CancellationToken stoppingToken,IDataLoaderService loaderService)
{
等待loaderService.Process();
}
专用异步任务DoAnotherWork(取消令牌停止工作,IDataLoaderService loaderService)
{
等待loaderService.Validate();
}
}
如果您不想在您的案例中使用现有的调度库,您可以使用两个计时器,就像在这里一样,其中使用了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();
}
}
公共类工作者:IHostedService,IDisposable
{
专用读写器ViceScopeFactory\u scopeFactory;
专用IDataLoaderService(数据加载服务);;
专用定时器_timer1;
专用定时器_timer2;
公共任务StartSync(CancellationToken CancellationToken)
{
_dataLoaderService=scope.ServiceProvider.GetRequiredService();
_timer1=新计时器(DoWork,null,TimeSpan.Zero,TimeSpan.FromSeconds(300));
_timer2=新计时器(DoAnotherWork,null,TimeSpan.Zero,TimeSpan.FromSeconds(600));
返回Task.CompletedTask;
}
专用异步void DoWork(对象)
{
//或者在此处创建范围并解析
wait_loaderService.Process();
}
私有异步void DoAnotherWork(对象)
{
//或者在此处创建范围并解析
wait_loaderService.Validate();
}
公共任务StopAsync(CancellationToken stoppingToken)
{
_logger.LogInformation(“定时托管服务正在停止”);
_timer1?.Change(Timeout.Infinite,0);
_timer2?更改(Timeout.Infinite,0);
返回Task.CompletedTask;
}
公共空间处置()
{
_timer1?.Dispose();
_timer2?.Dispose();
}
}
这两个任务可以并行运行,并且互不依赖
听起来你有两项服务:
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
}
}
}
公共类ProcessDataLoaderWorker:BackgroundService
{
专用读写器ViceScopeFactory\u scopeFactory;
受保护的覆盖异步任务ExecuteAsync(CancellationToken stoppingToken)
{
使用var scope=_scopeFactory.CreateScope();
var dataLoaderService=scope.ServiceProvider.GetRequiredService();
while(true)
{
等待dataLoaderService.Process();
等待任务。延迟(TimeSpan.FromMinutes(5),stoppingToken);//每5分钟运行一次
}
}
}
公共类ValidateDataLoaderWorker:后台服务
{
专用读写器ViceScopeFactory\u scopeFactory;
受保护的覆盖异步任务ExecuteAsync(CancellationToken stoppingToken)
{
使用var scope=_scopeFactory.CreateScope();
var dataLoaderService=scope.ServiceProvider.GetRequiredService();
while(true)
{
等待dataLoaderService.Validate();
等待任务。延迟(TimeSpan.FromMinutes(10),stoppingToken);//每10分钟运行一次
}
}
}
我还修改了
IDataLoaderService
的使用方式,使其不在其范围之外使用,并更改了任务。延迟
参数,使其更易于解释。如果您不想使用Hangfire或Quartz,可以使用其中一个计时器(例如)@GuruStron你能详细说明我如何在ExecuteAsync
或StartAsync
方法中使用Timer
吗?使用IHostedService
比BackgroundService
有什么好处吗?@Shaggy你不需要考虑从哪里开始计时=)明白了。我试过你的代码,不知道为什么,但它只是立即执行DoWork
不会每5分钟调用一次。BackgroundService
现在更适用。@Pure.Krome为什么会这样?我会在循环之前添加一个Wait Task.Yield()
,因为在第一次wait
之前出现异常会导致启动失败。@Jeremylakman:I通常情况下。@StephenCleary这里有两个问题:1)这两个问题是如何“连接”起来的?2) 为什么在(!stoppingToken.IsCancellationRequested)时使用while(true)
而不是while(!stoppingToken.IsCancellationRequested)
。。如果要求取消。。。然后,这将优雅地结束这两个后台任务?@Pure.Krome:1)您可以使用AddHostedService
添加多个服务。2) NET中的标准取消模式是抛出OperationCanceledException
,因此我强烈避免IsCancellationReq