Files
XplorePlane/XplorePlane/Services/AppState/AppStateService.cs
T
2026-03-23 14:04:53 +08:00

230 lines
9.6 KiB
C#

using System;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using Prism.Mvvm;
using XP.Common.Logging.Interfaces;
using XP.Hardware.RaySource.Services;
using XplorePlane.Models;
namespace XplorePlane.Services.AppState
{
/// <summary>
/// 全局应用状态管理服务实现。
/// 继承 BindableBase 以支持 WPF 数据绑定,使用 Interlocked.Exchange 保证线程安全写入,
/// 通过 Dispatcher.BeginInvoke 将事件调度到 UI 线程。
/// </summary>
public class AppStateService : BindableBase, IAppStateService
{
private readonly Dispatcher _dispatcher;
private readonly IRaySourceService _raySourceService;
private readonly ILoggerService _logger;
private bool _disposed;
// ── 状态字段(通过 Interlocked.Exchange 原子替换)──
private MotionState _motionState = MotionState.Default;
private RaySourceState _raySourceState = RaySourceState.Default;
private DetectorState _detectorState = DetectorState.Default;
private SystemState _systemState = SystemState.Default;
private CameraState _cameraState = CameraState.Default;
private CalibrationMatrix _calibrationMatrix;
private LinkedViewState _linkedViewState = LinkedViewState.Default;
private RecipeExecutionState _recipeExecutionState = RecipeExecutionState.Default;
// ── 类型化状态变更事件 ──
public event EventHandler<StateChangedEventArgs<MotionState>> MotionStateChanged;
public event EventHandler<StateChangedEventArgs<RaySourceState>> RaySourceStateChanged;
public event EventHandler<StateChangedEventArgs<DetectorState>> DetectorStateChanged;
public event EventHandler<StateChangedEventArgs<SystemState>> SystemStateChanged;
public event EventHandler<StateChangedEventArgs<CameraState>> CameraStateChanged;
public event EventHandler<StateChangedEventArgs<LinkedViewState>> LinkedViewStateChanged;
public event EventHandler<StateChangedEventArgs<RecipeExecutionState>> RecipeExecutionStateChanged;
public event EventHandler<LinkedViewRequestEventArgs> LinkedViewRequested;
// ── 状态属性(只读)──
public MotionState MotionState => _motionState;
public RaySourceState RaySourceState => _raySourceState;
public DetectorState DetectorState => _detectorState;
public SystemState SystemState => _systemState;
public CameraState CameraState => _cameraState;
public CalibrationMatrix CalibrationMatrix => _calibrationMatrix;
public LinkedViewState LinkedViewState => _linkedViewState;
public RecipeExecutionState RecipeExecutionState => _recipeExecutionState;
public AppStateService(
IRaySourceService raySourceService,
ILoggerService logger)
{
ArgumentNullException.ThrowIfNull(raySourceService);
ArgumentNullException.ThrowIfNull(logger);
_raySourceService = raySourceService;
_logger = logger.ForModule<AppStateService>();
_dispatcher = Application.Current.Dispatcher;
SubscribeToExistingServices();
_logger.Info("AppStateService 已初始化");
}
// ── 状态更新方法 ──
public void UpdateMotionState(MotionState newState)
{
ArgumentNullException.ThrowIfNull(newState);
if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateMotionState 调用"); return; }
var old = Interlocked.Exchange(ref _motionState, newState);
if (ReferenceEquals(old, newState)) return;
RaiseOnDispatcher(old, newState, MotionStateChanged, nameof(MotionState));
}
public void UpdateRaySourceState(RaySourceState newState)
{
ArgumentNullException.ThrowIfNull(newState);
if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateRaySourceState 调用"); return; }
var old = Interlocked.Exchange(ref _raySourceState, newState);
if (ReferenceEquals(old, newState)) return;
RaiseOnDispatcher(old, newState, RaySourceStateChanged, nameof(RaySourceState));
}
public void UpdateDetectorState(DetectorState newState)
{
ArgumentNullException.ThrowIfNull(newState);
if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateDetectorState 调用"); return; }
var old = Interlocked.Exchange(ref _detectorState, newState);
if (ReferenceEquals(old, newState)) return;
RaiseOnDispatcher(old, newState, DetectorStateChanged, nameof(DetectorState));
}
public void UpdateSystemState(SystemState newState)
{
ArgumentNullException.ThrowIfNull(newState);
if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateSystemState 调用"); return; }
var old = Interlocked.Exchange(ref _systemState, newState);
if (ReferenceEquals(old, newState)) return;
RaiseOnDispatcher(old, newState, SystemStateChanged, nameof(SystemState));
}
public void UpdateCameraState(CameraState newState)
{
ArgumentNullException.ThrowIfNull(newState);
if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateCameraState 调用"); return; }
var old = Interlocked.Exchange(ref _cameraState, newState);
if (ReferenceEquals(old, newState)) return;
RaiseOnDispatcher(old, newState, CameraStateChanged, nameof(CameraState));
}
public void UpdateCalibrationMatrix(CalibrationMatrix newMatrix)
{
ArgumentNullException.ThrowIfNull(newMatrix);
if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateCalibrationMatrix 调用"); return; }
var old = Interlocked.Exchange(ref _calibrationMatrix, newMatrix);
if (ReferenceEquals(old, newMatrix)) return;
_dispatcher.BeginInvoke(() =>
{
RaisePropertyChanged(nameof(CalibrationMatrix));
});
}
public void UpdateLinkedViewState(LinkedViewState newState)
{
ArgumentNullException.ThrowIfNull(newState);
if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateLinkedViewState 调用"); return; }
var old = Interlocked.Exchange(ref _linkedViewState, newState);
if (ReferenceEquals(old, newState)) return;
RaiseOnDispatcher(old, newState, LinkedViewStateChanged, nameof(LinkedViewState));
}
public void UpdateRecipeExecutionState(RecipeExecutionState newState)
{
ArgumentNullException.ThrowIfNull(newState);
if (_disposed) { _logger.Warn("AppStateService 已释放,忽略 UpdateRecipeExecutionState 调用"); return; }
var old = Interlocked.Exchange(ref _recipeExecutionState, newState);
if (ReferenceEquals(old, newState)) return;
RaiseOnDispatcher(old, newState, RecipeExecutionStateChanged, nameof(RecipeExecutionState));
}
// ── 画面联动 ──
public void RequestLinkedView(double pixelX, double pixelY)
{
var matrix = _calibrationMatrix;
if (matrix is null)
{
_logger.Warn("CalibrationMatrix 未设置,无法执行画面联动 (pixelX={PixelX}, pixelY={PixelY})", pixelX, pixelY);
UpdateSystemState(SystemState with
{
HasError = true,
ErrorMessage = "CalibrationMatrix 未设置,无法执行画面联动"
});
return;
}
var (x, y, z) = matrix.Transform(pixelX, pixelY);
var newLinkedState = new LinkedViewState(
new PhysicalPosition(x, y, z),
IsExecuting: true,
LastRequestTime: DateTime.UtcNow);
UpdateLinkedViewState(newLinkedState);
_dispatcher.BeginInvoke(() =>
{
LinkedViewRequested?.Invoke(this, new LinkedViewRequestEventArgs(x, y, z));
});
}
// ── 内部辅助方法 ──
private void RaiseOnDispatcher<T>(T oldVal, T newVal,
EventHandler<StateChangedEventArgs<T>> handler, string propertyName)
{
_dispatcher.BeginInvoke(() =>
{
RaisePropertyChanged(propertyName);
try
{
handler?.Invoke(this, new StateChangedEventArgs<T>(oldVal, newVal));
}
catch (Exception ex)
{
_logger.Error(ex, "状态变更事件处理器抛出异常 (property={PropertyName})", propertyName);
}
});
}
private void SubscribeToExistingServices()
{
_logger.Info("AppStateService 已准备好接收外部服务状态更新");
}
// ── Dispose ──
public void Dispose()
{
if (_disposed) return;
_disposed = true;
// 清除所有事件订阅
MotionStateChanged = null;
RaySourceStateChanged = null;
DetectorStateChanged = null;
SystemStateChanged = null;
CameraStateChanged = null;
LinkedViewStateChanged = null;
RecipeExecutionStateChanged = null;
LinkedViewRequested = null;
_logger.Info("AppStateService 已释放");
}
}
}