修复 AppState 审计第一/第二阶段问题:功能阻塞与事件/内存压力
- BGA 检测:流水线复用失败时删除无条件 return 死代码,回退到真实检测路径(原有仿真数据兜底不变) - MotionState 去重改用值比较(record Equals),避免设备静止时 100ms 轮询仍每次触发全量 UI 更新 - DetectorFramePipelineService 移除只写不读的 _acquireQueue,改为原子饱和计数器,不再让约 37MB/帧的图像常驻内存 - PerformanceMonitorViewModel 订阅事件改为具名处理器,Dispose 时完整反订阅,避免调试面板重复开关造成泄漏 Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -790,7 +790,7 @@ namespace XplorePlane.Services.AppState
|
||||
private void SetMotionState(MotionState newState)
|
||||
{
|
||||
var old = Interlocked.Exchange(ref _motionState, newState);
|
||||
if (ReferenceEquals(old, newState)) return;
|
||||
if (old == newState) return;
|
||||
RaiseOnDispatcher(old, newState, MotionStateChanged, nameof(MotionState));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace XplorePlane.Services.Main.Viewport
|
||||
|
||||
public sealed class DetectorFramePipelineService : IDetectorFramePipelineService
|
||||
{
|
||||
private readonly ConcurrentQueue<DetectorFrame> _acquireQueue = new();
|
||||
private readonly ConcurrentQueue<DetectorFrame> _processQueue = new();
|
||||
private readonly SemaphoreSlim _processSignal = new(0);
|
||||
private readonly CancellationTokenSource _shutdown = new();
|
||||
@@ -110,7 +109,8 @@ namespace XplorePlane.Services.Main.Viewport
|
||||
rawPixels: rawPixels,
|
||||
previewImage: bitmap);
|
||||
|
||||
EnqueueBounded(_acquireQueue, frame, AcquireQueueCapacity, ref _acquireQueueCount);
|
||||
// 仅维护饱和计数用于诊断展示,不持有帧对象本身,避免大尺寸帧在无消费者的情况下常驻内存。
|
||||
IncrementSaturating(ref _acquireQueueCount, AcquireQueueCapacity);
|
||||
_mainViewportService.UpdateDetectorFrame(frame);
|
||||
|
||||
var sequence = Interlocked.Increment(ref _receivedFrameCount);
|
||||
@@ -168,6 +168,18 @@ namespace XplorePlane.Services.Main.Viewport
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>递增计数并夹到容量上限,用于无实际队列时的诊断计数。</summary>
|
||||
private static void IncrementSaturating(ref int count, int capacity)
|
||||
{
|
||||
int current, next;
|
||||
do
|
||||
{
|
||||
current = Volatile.Read(ref count);
|
||||
next = Math.Min(current + 1, capacity);
|
||||
}
|
||||
while (Interlocked.CompareExchange(ref count, next, current) != current);
|
||||
}
|
||||
|
||||
private static int ReadInt(string key, int defaultValue, int minValue)
|
||||
{
|
||||
var raw = ConfigurationManager.AppSettings[key];
|
||||
|
||||
@@ -81,19 +81,27 @@ namespace XplorePlane.ViewModels.Debug
|
||||
return;
|
||||
}
|
||||
|
||||
_appStateService.MotionStateChanged += (_, _) => RecordEvent("MotionState");
|
||||
_appStateService.RaySourceStateChanged += (_, _) => RecordEvent("RaySourceState");
|
||||
_appStateService.DetectorStateChanged += (_, _) => RecordEvent("DetectorState");
|
||||
_appStateService.SystemStateChanged += (_, _) => RecordEvent("SystemState");
|
||||
_appStateService.CameraStateChanged += (_, _) => RecordEvent("CameraState");
|
||||
_appStateService.LinkedViewStateChanged += (_, _) => RecordEvent("LinkedViewState");
|
||||
_appStateService.RecipeExecutionStateChanged += (_, _) => RecordEvent("RecipeExecutionState");
|
||||
_appStateService.MotionStateChanged += OnMotionStateChanged;
|
||||
_appStateService.RaySourceStateChanged += OnRaySourceStateChanged;
|
||||
_appStateService.DetectorStateChanged += OnDetectorStateChanged;
|
||||
_appStateService.SystemStateChanged += OnSystemStateChanged;
|
||||
_appStateService.CameraStateChanged += OnCameraStateChanged;
|
||||
_appStateService.LinkedViewStateChanged += OnLinkedViewStateChanged;
|
||||
_appStateService.RecipeExecutionStateChanged += OnRecipeExecutionStateChanged;
|
||||
|
||||
_timer.Start();
|
||||
_initialized = true;
|
||||
}
|
||||
|
||||
/// <summary>释放资源:停止定时器 + 清空数据</summary>
|
||||
private void OnMotionStateChanged(object sender, StateChangedEventArgs<XplorePlane.Models.Main.MotionState> e) => RecordEvent("MotionState");
|
||||
private void OnRaySourceStateChanged(object sender, StateChangedEventArgs<XplorePlane.Models.Main.RaySourceState> e) => RecordEvent("RaySourceState");
|
||||
private void OnDetectorStateChanged(object sender, StateChangedEventArgs<XplorePlane.Models.Main.DetectorState> e) => RecordEvent("DetectorState");
|
||||
private void OnSystemStateChanged(object sender, StateChangedEventArgs<XplorePlane.Models.Main.SystemState> e) => RecordEvent("SystemState");
|
||||
private void OnCameraStateChanged(object sender, StateChangedEventArgs<XplorePlane.Models.Main.CameraState> e) => RecordEvent("CameraState");
|
||||
private void OnLinkedViewStateChanged(object sender, StateChangedEventArgs<XplorePlane.Models.Main.LinkedViewState> e) => RecordEvent("LinkedViewState");
|
||||
private void OnRecipeExecutionStateChanged(object sender, StateChangedEventArgs<XplorePlane.Models.Recipe.RecipeExecutionState> e) => RecordEvent("RecipeExecutionState");
|
||||
|
||||
/// <summary>释放资源:反订阅状态事件 + 停止定时器 + 清空数据</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
if (_disposed)
|
||||
@@ -101,6 +109,17 @@ namespace XplorePlane.ViewModels.Debug
|
||||
return;
|
||||
}
|
||||
|
||||
if (_initialized)
|
||||
{
|
||||
_appStateService.MotionStateChanged -= OnMotionStateChanged;
|
||||
_appStateService.RaySourceStateChanged -= OnRaySourceStateChanged;
|
||||
_appStateService.DetectorStateChanged -= OnDetectorStateChanged;
|
||||
_appStateService.SystemStateChanged -= OnSystemStateChanged;
|
||||
_appStateService.CameraStateChanged -= OnCameraStateChanged;
|
||||
_appStateService.LinkedViewStateChanged -= OnLinkedViewStateChanged;
|
||||
_appStateService.RecipeExecutionStateChanged -= OnRecipeExecutionStateChanged;
|
||||
}
|
||||
|
||||
_timer.Stop();
|
||||
Metrics.Clear();
|
||||
TrendData.Clear();
|
||||
|
||||
@@ -634,12 +634,11 @@ namespace XplorePlane.ViewModels.Inspection.TaskWizard
|
||||
}
|
||||
|
||||
_logger.LogWarning(
|
||||
"[BGA-Pipeline] 未找到流水线 BgaVoidRate 输出,operator={Operator}, keys={Keys}",
|
||||
"[BGA-Pipeline] 未找到流水线 BgaVoidRate 输出,operator={Operator}, keys={Keys},回退到真实检测路径",
|
||||
_viewportService?.LatestPipelineOperatorKey ?? string.Empty,
|
||||
_viewportService?.LatestPipelineOutputData == null
|
||||
? "none"
|
||||
: string.Join(",", _viewportService.LatestPipelineOutputData.Keys));
|
||||
return;
|
||||
|
||||
_logger.LogInformation("▶ ExecuteRunBgaDetection 开始");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user