Files
DMS/DMS.Infrastructure/Services/OpcUa/OptimizedOpcUaBackgroundService.cs
David P.G b85ffdc21b 1 feat: 重构数据加载完成事件的处理机制
2
    3 - 从IDataLoaderService接口中移除OnLoadDataCompleted事件
    4 - 在IEventService接口中新增OnLoadDataCompleted事件和RaiseLoadDataCompleted方法
    5 - 在EventService实现类中实现数据加载完成事件的触发功能
    6 - 修改DataLoaderService不再直接触发事件,而是通过IEventService来触发
    7 - 更新MQTT、OPC UA和S7后台服务以订阅事件服务中的数据加载完成事件
    8 - 修改数据加载完成事件的监听方式,统一使用事件服务进行管理
    9
   10 此重构改进了事件处理的架构设计,使事件管理更加集中和一致。
2025-10-05 11:21:05 +08:00

158 lines
6.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using DMS.Application.DTOs;
using DMS.Application.Events;
using DMS.Application.Interfaces;
using DMS.Core.Enums;
using DMS.Infrastructure.Interfaces.Services;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace DMS.Infrastructure.Services.OpcUa
{
/// <summary>
/// 优化后的OPC UA后台服务
/// </summary>
public class OptimizedOpcUaBackgroundService : BackgroundService
{
private readonly IAppDataCenterService _appDataCenterService;
private readonly IAppDataStorageService _appDataStorageService;
private readonly IEventService _eventService;
private readonly IOpcUaServiceManager _opcUaServiceManager;
private readonly ILogger<OptimizedOpcUaBackgroundService> _logger;
private readonly SemaphoreSlim _reloadSemaphore = new SemaphoreSlim(0);
public OptimizedOpcUaBackgroundService(
IAppDataCenterService appDataCenterService,
IAppDataStorageService appDataStorageService,
IEventService eventService,
IOpcUaServiceManager opcUaServiceManager,
ILogger<OptimizedOpcUaBackgroundService> logger)
{
_appDataCenterService = appDataCenterService ?? throw new ArgumentNullException(nameof(appDataCenterService));
_appDataStorageService = appDataStorageService;
_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 (_appDataStorageService.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后台服务已停止");
}
/// <summary>
/// 加载并连接设备
/// </summary>
private async Task LoadAndConnectDevicesAsync(CancellationToken stoppingToken)
{
_logger.LogInformation("开始加载和连接OPC UA设备...");
try
{
// 获取所有活动的OPC UA设备
var opcUaDevices = _appDataStorageService.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<VariableDto>();
_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后台服务资源已释放");
}
}
}