using DMS.Application.DTOs; using DMS.Application.Events; using DMS.Application.Interfaces; using DMS.Core.Enums; using DMS.Core.Models; using DMS.Infrastructure.Interfaces.Services; using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Logging; namespace DMS.Infrastructure.Services.OpcUa { /// /// 优化后的OPC UA后台服务 /// public class OptimizedOpcUaBackgroundService : BackgroundService { private readonly IAppCenterService _appCenterService; private readonly IAppStorageService _appStorageService; private readonly IEventService _eventService; private readonly IOpcUaServiceManager _opcUaServiceManager; private readonly ILogger _logger; private readonly SemaphoreSlim _reloadSemaphore = new SemaphoreSlim(0); public OptimizedOpcUaBackgroundService( IAppCenterService appCenterService, IAppStorageService appStorageService, IEventService eventService, IOpcUaServiceManager opcUaServiceManager, ILogger logger) { _appCenterService = appCenterService ?? throw new ArgumentNullException(nameof(appCenterService)); _appStorageService = appStorageService; _opcUaServiceManager = opcUaServiceManager ?? throw new ArgumentNullException(nameof(opcUaServiceManager)); _logger = logger ?? throw new ArgumentNullException(nameof(logger)); _eventService = eventService; _eventService.OnLoadDataCompleted += OnLoadDataCompleted; } private void OnLoadDataCompleted(object sender, DataLoadCompletedEventArgs e) { _logger.LogInformation("收到数据加载完成通知,触发OPC UA服务重新加载"); _reloadSemaphore.Release(); } protected override async Task ExecuteAsync(CancellationToken stoppingToken) { _logger.LogInformation("优化后的OPC UA后台服务正在启动..."); try { // 初始化服务管理器 await _opcUaServiceManager.InitializeAsync(stoppingToken); while (!stoppingToken.IsCancellationRequested) { await _reloadSemaphore.WaitAsync(stoppingToken); if (stoppingToken.IsCancellationRequested) break; if (_appStorageService.Devices.IsEmpty) { _logger.LogInformation("没有可用的OPC UA设备,等待设备列表更新..."); continue; } await LoadAndConnectDevicesAsync(stoppingToken); } } catch (OperationCanceledException) { _logger.LogInformation("OPC UA后台服务已收到停止请求"); } catch (Exception ex) { _logger.LogError(ex, "OPC UA后台服务运行时发生未处理的异常: {ErrorMessage}", ex.Message); } finally { _logger.LogInformation("正在清理OPC UA后台服务资源..."); // 服务管理器会在Dispose时自动清理资源 } _logger.LogInformation("优化后的OPC UA后台服务已停止"); } /// /// 加载并连接设备 /// private async Task LoadAndConnectDevicesAsync(CancellationToken stoppingToken) { _logger.LogInformation("开始加载和连接OPC UA设备..."); try { // 获取所有活动的OPC UA设备 var opcUaDevices = _appStorageService.Devices.Values .Where(d => d.Protocol == ProtocolType.OpcUa ) .ToList(); _logger.LogInformation("找到 {DeviceCount} 个OPC UA设备", opcUaDevices.Count); if (opcUaDevices.Count == 0) return; // 添加设备到监控列表 foreach (var device in opcUaDevices) { _opcUaServiceManager.AddDevice(device); // 获取设备变量 var variables = device.VariableTables? .SelectMany(vt => vt.Variables) .Where(v => v.IsActive && v.Protocol == ProtocolType.OpcUa) .ToList() ?? new List(); _opcUaServiceManager.UpdateVariables(device.Id, variables); } // 批量连接设备 var deviceIds = opcUaDevices.Select(d => d.Id).ToList(); await _opcUaServiceManager.ConnectDevicesAsync(deviceIds, stoppingToken); _logger.LogInformation("OPC UA设备加载和连接完成"); } catch (Exception ex) { _logger.LogError(ex, "加载和连接OPC UA设备时发生错误: {ErrorMessage}", ex.Message); } } public override async Task StopAsync(CancellationToken cancellationToken) { _logger.LogInformation("正在停止OPC UA后台服务..."); // 释放信号量以确保ExecuteAsync可以退出 _reloadSemaphore.Release(); await base.StopAsync(cancellationToken); _logger.LogInformation("OPC UA后台服务停止完成"); } public override void Dispose() { _logger.LogInformation("正在释放OPC UA后台服务资源..."); _eventService.OnLoadDataCompleted -= OnLoadDataCompleted; _reloadSemaphore?.Dispose(); base.Dispose(); _logger.LogInformation("OPC UA后台服务资源已释放"); } } }