将Feature/XP.Common和Feature/XP.Hardware分支合并至Develop/XP.forHardwareAndCommon,完善XPapp注册和相关硬件类库通用类库功能。

This commit is contained in:
QI Mingxuan
2026-04-16 17:31:13 +08:00
parent 6ec4c3ddaa
commit 2bd6e566c3
581 changed files with 74600 additions and 222 deletions
@@ -0,0 +1,771 @@
using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Threading.Tasks;
using System.Windows;
using XP.Common.Helpers;
using XP.Common.Localization.Interfaces;
using XP.Common.Logging.Interfaces;
using XP.Hardware.RaySource.Abstractions;
using XP.Hardware.RaySource.Abstractions.Enums;
using XP.Hardware.RaySource.Abstractions.Events;
using XP.Hardware.RaySource.Config;
using XP.Hardware.RaySource.Services;
namespace XP.Hardware.RaySource.ViewModels
{
/// <summary>
/// 射线源操作视图模型 | X-Ray Source Operate ViewModel
/// 负责射线源开关控制、电压电流调节、状态监控 | Responsible for X-ray on/off control, voltage/current adjustment, status monitoring
/// </summary>
public class RaySourceOperateViewModel : BindableBase, IDisposable
{
#region | Fields
private readonly IRaySourceService _raySourceService;
private readonly IEventAggregator _eventAggregator;
private readonly RaySourceConfig _config;
private readonly ILoggerService _logger;
private readonly ILocalizationService _localizationService;
private bool _isDisposed = false;
private bool _isOperating = false;
private bool _isVariablesConnected = false;
private bool _autoInitialized = false;
private Views.RaySourceConfigWindow _configWindow;
/// <summary>
/// 标记当前是否正在从设备反馈更新值(防止 code-behind 误触发写入)
/// Flag indicating whether values are being updated from device feedback (prevents code-behind from triggering writes)
/// </summary>
public bool IsUpdatingFromDevice { get; private set; } = false;
#endregion
#region | Status Properties
private RaySourceStatus _raySourceStatus = RaySourceStatus.Unavailable;
/// <summary>
/// 射线源状态(不可用/关闭/开启)| X-ray source status (Unavailable/Closed/Opened)
/// </summary>
public RaySourceStatus RaySourceStatus
{
get => _raySourceStatus;
set
{
if (SetProperty(ref _raySourceStatus, value))
{
RaisePropertyChanged(nameof(StatusText));
RaisePropertyChanged(nameof(IsSlidersEnabled));
TurnOnCommand?.RaiseCanExecuteChanged();
TurnOffCommand?.RaiseCanExecuteChanged();
}
}
}
/// <summary>
/// 状态文本(绑定到腰圆内的文字)| Status text (bound to capsule text)
/// </summary>
public string StatusText
{
get
{
return RaySourceStatus switch
{
RaySourceStatus.Unavailable => $"{_localizationService.GetString("RaySource_StatusUnavailable")}",
RaySourceStatus.Closed => _localizationService.GetString("RaySource_StatusClosed"),
RaySourceStatus.Opened => _localizationService.GetString("RaySource_StatusOpened"),
_ => _localizationService.GetString("RaySource_StatusUnavailable")
};
}
}
/// <summary>
/// 滑块是否启用(仅服务已初始化时可调节)| Sliders enabled (only when service is initialized)
/// </summary>
public bool IsSlidersEnabled => _raySourceService.IsInitialized && _isVariablesConnected;
/// <summary>
/// PVI 变量是否已连接 | Whether PVI variables are connected
/// </summary>
public bool IsVariablesConnected
{
get => _isVariablesConnected;
private set
{
if (SetProperty(ref _isVariablesConnected, value))
{
RaisePropertyChanged(nameof(IsSlidersEnabled));
TurnOnCommand?.RaiseCanExecuteChanged();
TurnOffCommand?.RaiseCanExecuteChanged();
}
}
}
private bool _isInterlockActive;
/// <summary>
/// 连锁是否激活 | Whether interlock is active
/// </summary>
public bool IsInterlockActive
{
get => _isInterlockActive;
private set
{
if (SetProperty(ref _isInterlockActive, value))
{
TurnOnCommand?.RaiseCanExecuteChanged();
}
}
}
#endregion
#region | Voltage Properties
private double _voltageMin;
/// <summary>
/// 电压最小值(kV| Voltage minimum (kV)
/// </summary>
public double VoltageMin
{
get => _voltageMin;
set => SetProperty(ref _voltageMin, value);
}
private double _voltageMax;
/// <summary>
/// 电压最大值(kV| Voltage maximum (kV)
/// </summary>
public double VoltageMax
{
get => _voltageMax;
set => SetProperty(ref _voltageMax, value);
}
private double _voltageValue;
/// <summary>
/// 电压滑块值(kV),仅更新UI显示,不自动写入硬件 | Voltage slider value (kV), UI display only, no auto write to hardware
/// </summary>
public double VoltageValue
{
get => _voltageValue;
set => SetProperty(ref _voltageValue, Math.Round(value, 0));
}
private double _voltageActual;
/// <summary>
/// 电压实际值(kV| Voltage actual value (kV)
/// </summary>
public double VoltageActual
{
get => _voltageActual;
set => SetProperty(ref _voltageActual, value);
}
/// <summary>
/// 电压实际值显示文本 | Voltage actual value display text
/// </summary>
public string VoltageActualText => string.Format(_localizationService.GetString("RaySource_ActualValueLabel"), VoltageActual.ToString("F1"));
#endregion
#region | Current Properties
private double _currentMin;
/// <summary>
/// 电流最小值(μA| Current minimum (μA)
/// </summary>
public double CurrentMin
{
get => _currentMin;
set => SetProperty(ref _currentMin, value);
}
private double _currentMax;
/// <summary>
/// 电流最大值(μA| Current maximum (μA)
/// </summary>
public double CurrentMax
{
get => _currentMax;
set => SetProperty(ref _currentMax, value);
}
private double _currentValue;
/// <summary>
/// 电流滑块值(μA),仅更新UI显示,不自动写入硬件 | Current slider value (μA), UI display only, no auto write to hardware
/// </summary>
public double CurrentValue
{
get => _currentValue;
set => SetProperty(ref _currentValue, Math.Round(value, 0));
}
private double _currentActual;
/// <summary>
/// 电流实际值(μA| Current actual value (μA)
/// </summary>
public double CurrentActual
{
get => _currentActual;
set => SetProperty(ref _currentActual, value);
}
/// <summary>
/// 电流实际值显示文本 | Current actual value display text
/// </summary>
public string CurrentActualText => string.Format(_localizationService.GetString("RaySource_ActualValueLabel"), CurrentActual.ToString("F1"));
#endregion
#region | Commands
/// <summary>
/// 开启射线源命令 | Turn on X-ray command
/// </summary>
public DelegateCommand TurnOnCommand { get; }
/// <summary>
/// 关闭射线源命令 | Turn off X-ray command
/// </summary>
public DelegateCommand TurnOffCommand { get; }
/// <summary>
/// 提交电压值命令(滑块松手/输入框失焦时触发)| Apply voltage command (triggered on slider drag complete / input lost focus)
/// </summary>
public DelegateCommand ApplyVoltageCommand { get; }
/// <summary>
/// 提交电流值命令(滑块松手/输入框失焦时触发)| Apply current command (triggered on slider drag complete / input lost focus)
/// </summary>
public DelegateCommand ApplyCurrentCommand { get; }
/// <summary>
/// 设置命令(预留接口)| Settings command (reserved interface)
/// </summary>
public DelegateCommand SettingsCommand { get; }
/// <summary>
/// 配置命令(打开射线源配置窗口)| Config command (open ray source config window)
/// </summary>
public DelegateCommand ConfigCommand { get; }
#endregion
#region | Constructor
/// <summary>
/// 构造函数 | Constructor
/// </summary>
public RaySourceOperateViewModel(
IRaySourceService raySourceService,
IEventAggregator eventAggregator,
RaySourceConfig config,
ILoggerService logger,
ILocalizationService localizationService)
{
_raySourceService = raySourceService ?? throw new ArgumentNullException(nameof(raySourceService));
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
_config = config ?? throw new ArgumentNullException(nameof(config));
_logger = (logger ?? throw new ArgumentNullException(nameof(logger))).ForModule("RaySource.ViewModel");
_localizationService = localizationService ?? throw new ArgumentNullException(nameof(localizationService));
_logger.Info("射线源操作视图模型已创建 | X-ray source operate view model created");
// 初始化极值 | Initialize min/max values
VoltageMin = _config.MinVoltage;
VoltageMax = _config.MaxVoltage;
CurrentMin = _config.MinCurrent;
CurrentMax = _config.MaxCurrent;
// 初始化滑块默认值 | Initialize slider default values
VoltageValue = _config.MinVoltage; //中间值:(_config.MinVoltage + _config.MaxVoltage) / 2;
CurrentValue = _config.MinCurrent; //中间值:(_config.MinCurrent + _config.MaxCurrent) / 2;
// 初始化命令 | Initialize commands
TurnOnCommand = new DelegateCommand(ExecuteTurnOn, CanExecuteTurnOn);
TurnOffCommand = new DelegateCommand(ExecuteTurnOff, CanExecuteTurnOff);
ApplyVoltageCommand = new DelegateCommand(ApplyVoltage);
ApplyCurrentCommand = new DelegateCommand(ApplyCurrent);
SettingsCommand = new DelegateCommand(ExecuteSettings, CanExecuteSettings);
ConfigCommand = new DelegateCommand(ExecuteConfig);
// 订阅事件 | Subscribe to events
SubscribeEvents();
// 初始化状态 | Initialize status
UpdateStatusFromService();
}
#endregion
#region | Event Subscription
/// <summary>
/// 订阅事件 | Subscribe to events
/// </summary>
private void SubscribeEvents()
{
// 订阅射线源状态变更事件(三态)| Subscribe to ray source status changed event (tri-state)
_eventAggregator.GetEvent<RaySourceStatusChangedEvent>().Subscribe(OnRaySourceStatusChanged, ThreadOption.UIThread);
// 订阅状态更新事件 | Subscribe to status updated event
_eventAggregator.GetEvent<StatusUpdatedEvent>().Subscribe(OnStatusUpdated, ThreadOption.UIThread);
// 订阅错误事件 | Subscribe to error event
_eventAggregator.GetEvent<ErrorOccurredEvent>().Subscribe(OnErrorOccurred, ThreadOption.UIThread);
// 订阅操作结果事件 | Subscribe to operation result event
_eventAggregator.GetEvent<OperationResultEvent>().Subscribe(OnOperationResult, ThreadOption.UIThread);
// 订阅变量连接状态变更事件 | Subscribe to variables connected event
_eventAggregator.GetEvent<VariablesConnectedEvent>().Subscribe(OnVariablesConnectedChanged, ThreadOption.UIThread);
}
/// <summary>
/// 射线源状态变更事件处理(三态)| Ray source status changed event handler (tri-state)
/// </summary>
private void OnRaySourceStatusChanged(RaySourceStatus newStatus)
{
var previousStatus = RaySourceStatus;
RaySourceStatus = newStatus;
RaisePropertyChanged(nameof(IsSlidersEnabled));
// 连接恢复处理:从不可用变为已连接,主动读取最新状态刷新UI | Connection restored: from unavailable to connected, actively read latest status to refresh UI
if (previousStatus == RaySourceStatus.Unavailable &&
(newStatus == RaySourceStatus.Opened || newStatus == RaySourceStatus.Closed))
{
_logger.Info("射线源连接已建立 | Ray Source Connected");
}
// 异常断联处理:从已连接状态变为不可用 | Handle unexpected disconnection: from connected to unavailable
if (newStatus == RaySourceStatus.Unavailable &&
(previousStatus == RaySourceStatus.Opened || previousStatus == RaySourceStatus.Closed))
{
// 断联时重置变量连接状态 | Reset variable connection state on disconnection
IsVariablesConnected = false;
_logger.Warn("ViewModel 检测到连接丢失(状态变为 Unavailable| ViewModel detected connection lost (status changed to Unavailable)");
//MessageBox.Show("射线源连接丢失,请检查设备连接后重新初始化。", "连接丢失", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
/// <summary>
/// 状态更新事件处理 | Status updated event handler
/// 仅在实际值真正变化时更新滑块/输入框,避免无意义赋值触发事件链
/// Only update slider/input when actual value truly changed, avoiding unnecessary assignment triggering event chain
/// </summary>
private void OnStatusUpdated(SystemStatusData statusData)
{
if (statusData == null) return;
IsUpdatingFromDevice = true;
try
{
// 电压实际值变化时,仅更新实际值标签显示 | When actual voltage changes, only update actual value label
if (Math.Abs(statusData.ActualVoltage - VoltageActual) > 0.01)
{
VoltageActual = statusData.ActualVoltage;
RaisePropertyChanged(nameof(VoltageActualText));
}
// 电流实际值变化时,仅更新实际值标签显示 | When actual current changes, only update actual value label
if (Math.Abs(statusData.ActualCurrent - CurrentActual) > 0.01)
{
CurrentActual = statusData.ActualCurrent;
RaisePropertyChanged(nameof(CurrentActualText));
}
// 设定电压反馈同步到滑块(仅设备反馈时更新,人工操作时 IsUpdatingFromDevice=false 不会进入此处)
// Sync set voltage feedback to slider (only during device feedback, not during manual operation)
if (statusData.SetVoltage >= _config.MinVoltage && Math.Abs(statusData.SetVoltage - VoltageValue) > 0.5)
{
VoltageValue = Math.Round(statusData.SetVoltage, 0);
}
// 设定电流反馈同步到滑块 | Sync set current feedback to slider
if (statusData.SetCurrent >= _config.MinCurrent && Math.Abs(statusData.SetCurrent - CurrentValue) > 0.5)
{
CurrentValue = Math.Round(statusData.SetCurrent, 0);
}
// 使用服务层的权威状态 | Use authoritative status from service layer
RaySourceStatus = _raySourceService.CurrentStatus;
// 同步连锁状态 | Sync interlock status
IsInterlockActive = statusData.IsInterlockActive;
}
finally
{
IsUpdatingFromDevice = false;
}
}
/// <summary>
/// 错误事件处理 | Error event handler
/// </summary>
private void OnErrorOccurred(string errorMessage)
{
// 显示错误消息 | Show error message
MessageBox.Show(errorMessage, "错误", MessageBoxButton.OK, MessageBoxImage.Error);
}
/// <summary>
/// 操作结果事件处理 | Operation result event handler
/// </summary>
private void OnOperationResult(OperationResultData resultData)
{
if (resultData == null) return;
if (!resultData.IsSuccess)
{
// 操作失败时显示消息 | Show message when operation fails
MessageBox.Show(resultData.Message, "操作失败", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
/// <summary>
/// 变量连接状态变更事件处理 | Variables connected state changed event handler
/// </summary>
private void OnVariablesConnectedChanged(bool isConnected)
{
IsVariablesConnected = isConnected;
_logger.Info("收到变量连接状态变更: {IsConnected} | Received variables connection state change: {IsConnected}", isConnected);
if (isConnected)
{
_logger.Info("变量已连接,主动读取最新状态 | Variables Connected, actively reading latest status");
RefreshStatusFromDevice();
}
}
#endregion
#region | Command Execution Logic
/// <summary>
/// 开启射线源执行逻辑 | Turn on X-ray execution logic
/// </summary>
private void ExecuteTurnOn()
{
_isOperating = true;
TurnOnCommand.RaiseCanExecuteChanged();
TurnOffCommand.RaiseCanExecuteChanged();
try
{
_logger.Info("用户请求开启射线 | User requested to turn on X-ray");
var result = _raySourceService.TurnOn();
if (result.Success)
{
_logger.Info("射线开启指令发送成功 | X-ray turned on successfully");
}
else
{
_logger.Warn("射线开启指令发送失败: {Error} | X-ray turn on failed: {Error}", result.ErrorMessage);
MessageBox.Show(result.ErrorMessage, "开启失败", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception ex)
{
_logger.Error(ex, "开启射线源异常: {Message} | Exception turning on X-ray: {Message}", ex.Message);
MessageBox.Show($"开启射线源异常: {ex.Message}", "异常", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
_isOperating = false;
TurnOnCommand.RaiseCanExecuteChanged();
TurnOffCommand.RaiseCanExecuteChanged();
}
}
/// <summary>
/// 开启命令是否可执行(仅关闭状态且连锁激活时可执行)| Can execute turn on command (only when closed and interlock active)
/// </summary>
private bool CanExecuteTurnOn()
{
return !_isOperating && _isVariablesConnected && IsInterlockActive && RaySourceStatus == RaySourceStatus.Closed && _raySourceService.IsInitialized;
}
/// <summary>
/// 关闭射线源执行逻辑 | Turn off X-ray execution logic
/// </summary>
private void ExecuteTurnOff()
{
_isOperating = true;
TurnOnCommand.RaiseCanExecuteChanged();
TurnOffCommand.RaiseCanExecuteChanged();
try
{
_logger.Info("用户请求关闭射线 | User requested to turn off X-ray");
var result = _raySourceService.TurnOff();
if (result.Success)
{
_logger.Info("射线关闭指令发送成功 | X-ray turned off successfully");
}
else
{
_logger.Warn("射线关闭指令发送失败: {Error} | X-ray turn off failed: {Error}", result.ErrorMessage);
MessageBox.Show(result.ErrorMessage, "关闭失败", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
catch (Exception ex)
{
_logger.Error(ex, "关闭射线源异常: {Message} | Exception turning off X-ray: {Message}", ex.Message);
MessageBox.Show($"关闭射线源异常: {ex.Message}", "异常", MessageBoxButton.OK, MessageBoxImage.Error);
}
finally
{
_isOperating = false;
TurnOnCommand.RaiseCanExecuteChanged();
TurnOffCommand.RaiseCanExecuteChanged();
}
}
/// <summary>
/// 关闭命令是否可执行(仅开启状态可执行)| Can execute turn off command (only when opened)
/// </summary>
private bool CanExecuteTurnOff()
{
return !_isOperating && _isVariablesConnected && RaySourceStatus == RaySourceStatus.Opened && _raySourceService.IsInitialized;
}
/// <summary>
/// 设置命令执行逻辑:打开外部高级设置程序 | Settings command: launch external advance settings program
/// 如果程序已运行则将窗口置前 | If program is already running, bring its window to front
/// </summary>
private void ExecuteSettings()
{
var exePath = _config.AdvanceExePath;
_logger.Info("用户点击高级按钮,目标程序: {ExePath} | User clicked advance button, target program: {ExePath}", exePath);
var result = ProcessHelper.StartOrActivate(exePath, true);
if (result.Success)
{
var action = result.IsNewlyStarted ? "已启动 | started" : "已激活 | activated";
_logger.Info("外部程序{Action} | External program {Action}", action, action);
}
else
{
_logger.Warn("外部程序操作失败: {Error} | External program operation failed: {Error}", result.ErrorMessage);
MessageBox.Show(result.ErrorMessage,
_localizationService.GetString("RaySource_Warning") ?? "警告",
MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
/// <summary>
/// 设置命令是否可执行 | Can execute settings command
/// </summary>
private bool CanExecuteSettings()
{
return true; // 始终可用 | Always available
}
/// <summary>
/// 配置命令执行逻辑:打开射线源配置窗口 | Config command: open ray source config window
/// </summary>
private void ExecuteConfig()
{
_logger.Info("用户点击配置按钮 | User clicked config button");
// 如果窗口已存在且未关闭,激活它而不是重复创建
if (_configWindow != null && _configWindow.IsLoaded)
{
_configWindow.Activate();
return;
}
_configWindow = new Views.RaySourceConfigWindow
{
Owner = Application.Current.MainWindow,
ShowInTaskbar = false
};
_configWindow.Closed += (s, e) => _configWindow = null;
_configWindow.Show();
}
/// <summary>
/// 提交电压值到硬件(滑块松手/输入框失焦时调用)| Apply voltage to hardware (called on slider drag complete / input lost focus)
/// </summary>
private void ApplyVoltage()
{
var voltage = (float)VoltageValue;
if (!IsSlidersEnabled) return;
// 范围校验 | Range validation
if (voltage < _config.MinVoltage || voltage > _config.MaxVoltage)
{
_logger.Warn("电压值超出范围: {Voltage}kV,忽略提交 | Voltage out of range: {Voltage}kV, ignoring apply", voltage);
return;
}
try
{
_logger.Debug("用户确认电压值: {Voltage}kV | User confirmed voltage: {Voltage}kV", voltage);
var result = _raySourceService.SetVoltage(voltage);
if (!result.Success)
{
_logger.Warn("电压设置失败: {Error} | Voltage setting failed: {Error}", result.ErrorMessage);
// 设置失败时恢复滑块值(仅当实际值在有效范围内时)| Restore slider value when setting fails (only when actual value is in valid range)
if (VoltageActual >= _config.MinVoltage)
VoltageValue = VoltageActual;
}
}
catch (Exception ex)
{
_logger.Error(ex, "设置电压异常: {Message} | Exception setting voltage: {Message}", ex.Message);
MessageBox.Show($"设置电压异常: {ex.Message}", "异常", MessageBoxButton.OK, MessageBoxImage.Error);
if (VoltageActual >= _config.MinVoltage)
VoltageValue = VoltageActual;
}
}
/// <summary>
/// 提交电流值到硬件(滑块松手/输入框失焦时调用)| Apply current to hardware (called on slider drag complete / input lost focus)
/// </summary>
private void ApplyCurrent()
{
var current = (float)CurrentValue;
if (!IsSlidersEnabled) return;
// 范围校验 | Range validation
if (current < _config.MinCurrent || current > _config.MaxCurrent)
{
_logger.Warn("电流值超出范围: {Current}μA,忽略提交 | Current out of range: {Current}μA, ignoring apply", current);
return;
}
try
{
_logger.Debug("用户确认电流值: {Current}μA | User confirmed current: {Current}μA", current);
var result = _raySourceService.SetCurrent(current);
if (!result.Success)
{
_logger.Warn("电流设置失败: {Error} | Current setting failed: {Error}", result.ErrorMessage);
// 设置失败时恢复滑块值(仅当实际值在有效范围内时)| Restore slider value when setting fails (only when actual value is in valid range)
if (CurrentActual >= _config.MinCurrent)
CurrentValue = CurrentActual;
}
}
catch (Exception ex)
{
_logger.Error(ex, "设置电流异常: {Message} | Exception setting current: {Message}", ex.Message);
MessageBox.Show($"设置电流异常: {ex.Message}", "异常", MessageBoxButton.OK, MessageBoxImage.Error);
if (CurrentActual >= _config.MinCurrent)
CurrentValue = CurrentActual;
}
}
/// <summary>
/// 从服务更新状态 | Update status from service
/// </summary>
private void UpdateStatusFromService()
{
RaySourceStatus = _raySourceService.CurrentStatus;
}
/// <summary>
/// 从设备主动读取最新状态并刷新UI | Actively read latest status from device and refresh UI
/// </summary>
private void RefreshStatusFromDevice()
{
try
{
var result = _raySourceService.ReadSystemStatus();
if (result.Success && result.Data is SystemStatusData statusData)
{
OnStatusUpdated(statusData);
_logger.Info("已从设备刷新最新状态 | Refreshed latest status from device");
}
else
{
_logger.Warn("读取设备状态失败: {Error} | Failed to read device status: {Error}", result.ErrorMessage);
}
}
catch (Exception ex)
{
_logger.Error(ex, "刷新设备状态异常: {Message} | Exception refreshing device status: {Message}", ex.Message);
}
}
/// <summary>
/// 界面加载时自动执行初始化和连接变量流程(仅执行一次)
/// Auto-execute Initialize and ConnectVariables on view loaded (runs only once)
/// </summary>
/// <summary>
/// 自动初始化:异步执行初始化 + 连接变量 | Auto-initialize: async Initialize + ConnectVariables
/// 由 View 的 Loaded 事件触发,仅执行一次 | Triggered by View's Loaded event, runs only once
/// </summary>
public async Task AutoInitializeAsync()
{
// 防止重复执行 | Prevent duplicate execution
if (_autoInitialized) return;
_autoInitialized = true;
// 如果已经初始化并连接,跳过 | Skip if already initialized and connected
if (_raySourceService.IsInitialized && _isVariablesConnected)
{
_logger.Info("射线源已初始化且变量已连接,跳过自动初始化 | Ray source already initialized and variables connected, skipping auto-init");
return;
}
_logger.Info("开始自动初始化流程 | Starting auto-initialization sequence");
var result = await _raySourceService.InitializeAndConnectAsync();
if (result.Success)
{
_logger.Info("自动初始化命令已发送,等待设备确认 | Auto-initialization command sent, waiting for device confirmation");
}
else
{
_logger.Warn("自动初始化流程失败: {Error} | Auto-initialization sequence failed: {Error}", result.ErrorMessage);
}
}
#endregion
#region IDisposable Implementation
/// <summary>
/// 释放资源 | Dispose resources
/// </summary>
public void Dispose()
{
if (!_isDisposed)
{
// 断开射线源连接 | Disconnect X-ray source
if (_raySourceService.IsInitialized)
{
_logger.Info("界面关闭,执行断开操作 | View closing, executing disconnect");
try
{
Task.Run(() => _raySourceService.Disconnect()).Wait(5000);
}
catch (Exception ex)
{
_logger.Warn("断开射线源异常: {Message} | Disconnect exception: {Message}", ex.Message);
}
}
// 关闭配置窗口 | Close config window
if (_configWindow != null && _configWindow.IsLoaded)
{
_configWindow.Close();
_configWindow = null;
}
// 取消订阅事件 | Unsubscribe events
_eventAggregator.GetEvent<RaySourceStatusChangedEvent>().Unsubscribe(OnRaySourceStatusChanged);
_eventAggregator.GetEvent<StatusUpdatedEvent>().Unsubscribe(OnStatusUpdated);
_eventAggregator.GetEvent<ErrorOccurredEvent>().Unsubscribe(OnErrorOccurred);
_eventAggregator.GetEvent<OperationResultEvent>().Unsubscribe(OnOperationResult);
_eventAggregator.GetEvent<VariablesConnectedEvent>().Unsubscribe(OnVariablesConnectedChanged);
_isDisposed = true;
}
}
#endregion
}
}