ASP.Net Core 5中两个后台服务周期性交替执行实现咨询
修改方案
要实现Task 01 → 延迟10秒 → Task 02 → 延迟10秒 → 重复循环的交替执行逻辑,需要重构原代码的执行流程,关键调整如下:
修改后的完整代码
public class RunTaskPeriodically : BackgroundService { private readonly IServiceScopeFactory _serviceScopeFactory; public RunTaskPeriodically(IServiceScopeFactory serviceScopeFactory) { _serviceScopeFactory = serviceScopeFactory; } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { // 执行Task 01 using (var scope = _serviceScopeFactory.CreateScope()) { Log.Information($"Task 01 Running"); var taskOne = scope.ServiceProvider.GetRequiredService<ITaskOne>(); await taskOne.DoTask(stoppingToken); } // 检查取消信号,避免无效延迟 if (stoppingToken.IsCancellationRequested) break; await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken); // 执行Task 02 using (var scope = _serviceScopeFactory.CreateScope()) { Log.Information($"Task 02 Running"); var taskTwo = scope.ServiceProvider.GetRequiredService<ITaskTwo>(); await taskTwo.DoTask(stoppingToken); } // 检查取消信号,避免无效延迟 if (stoppingToken.IsCancellationRequested) break; await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken); } } }
核心调整说明
拆分执行流程
将原有的「一次执行两个任务+延迟20秒」拆分为「单个任务执行+10秒延迟」的交替逻辑,完全匹配需求中的循环规则。独立服务范围
每个任务执行时单独创建IServiceScope,确保Scoped生命周期的服务能正确释放资源,避免长时间持有Scope导致的内存或状态问题。取消信号检查
每次延迟前增加取消令牌检查,确保后台服务能及时响应停止指令,避免在服务终止后仍执行不必要的任务或延迟。
可选优化:复用任务执行逻辑
如果后续需要扩展更多任务,可以将任务执行逻辑抽为私有方法,减少代码重复:
private async Task ExecuteTask<T>(string taskName, CancellationToken stoppingToken) where T : class { using (var scope = _serviceScopeFactory.CreateScope()) { Log.Information($"{taskName} Running"); var taskService = scope.ServiceProvider.GetRequiredService<T>(); if (taskService is ITaskOne taskOne) await taskOne.DoTask(stoppingToken); else if (taskService is ITaskTwo taskTwo) await taskTwo.DoTask(stoppingToken); } }
然后在ExecuteAsync中调用:
protected override async Task ExecuteAsync(CancellationToken stoppingToken) { while (!stoppingToken.IsCancellationRequested) { await ExecuteTask<ITaskOne>("Task 01", stoppingToken); if (stoppingToken.IsCancellationRequested) break; await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken); await ExecuteTask<ITaskTwo>("Task 02", stoppingToken); if (stoppingToken.IsCancellationRequested) break; await Task.Delay(TimeSpan.FromSeconds(10), stoppingToken); } }
内容的提问来源于stack exchange,提问作者Mehedi Hasan Kajol
相关产品推荐
相关产品推荐

