using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace YBEE.EQM.Application; public class ExamSampleWorker(ILogger logger, IServiceScopeFactory scopeFactory) : IHostedService, IDisposable { private readonly Dictionary _executingTasks = []; private readonly Dictionary _cancellationTokenSources = []; /// /// StartAsync 方法不再直接启动任务,而是保持服务初始化 /// /// /// public Task StartAsync(CancellationToken cancellationToken) { logger.LogInformation("抽样执行服务已初始化"); return Task.CompletedTask; } /// /// 外部控制:通过参数启动后台任务 /// /// 监测计划ID /// public int StartTask(int examPlanId) { if (_executingTasks.TryGetValue(examPlanId, out Task value) && !value.IsCompleted) { logger.LogInformation("监测计划ID:{examPlanId},执行中,不能重复启动!", examPlanId); return -1; } logger.LogInformation("监测计划ID:{examPlanId},开始执行...", examPlanId); var cancellationTokenSource = new CancellationTokenSource(); var executingTask = ExecuteAsync(examPlanId, cancellationTokenSource.Token); // 保存任务和取消令牌源,以便可以后续控制 _executingTasks[examPlanId] = executingTask; _cancellationTokenSources[examPlanId] = cancellationTokenSource; return 0; } /// /// 外部控制:通过任务参数停止任务 /// /// /// public int StopTask(int examPlanId) { if (!_executingTasks.TryGetValue(examPlanId, out Task value) || value.IsCompleted) { logger.LogInformation("监测计划ID:{examPlanId},未运行!", examPlanId); return -1; } logger.LogInformation("监测计划ID:{examPlanId},开始停止...", examPlanId); // 停止任务 _cancellationTokenSources[examPlanId]?.Cancel(); _executingTasks.Remove(examPlanId); _cancellationTokenSources.Remove(examPlanId); return 0; } /// /// 任务执行逻辑 /// /// /// /// private async Task ExecuteAsync(int examPlanId, CancellationToken cancellationToken) { try { while (!cancellationToken.IsCancellationRequested) { using var scope = scopeFactory.CreateScope(); var services = scope.ServiceProvider; var examSampleService = services.GetService(); await examSampleService.ExecuteSampleByExamPlanId(examPlanId); logger.LogInformation("监测计划ID:{examPlanId},执行完成。", examPlanId); StopTask(examPlanId); } } catch (TaskCanceledException) { logger.LogInformation("监测计划ID:{examPlanId},已取消。", examPlanId); } } public Task StopAsync(CancellationToken cancellationToken) { // 停止所有正在运行的任务 foreach (var key in _executingTasks.Keys.ToList()) { StopTask(key); } return Task.CompletedTask; } public void Dispose() { foreach (var cancellationTokenSource in _cancellationTokenSources.Values) { cancellationTokenSource?.Dispose(); } } }