Files
XplorePlane/XP.Hardware.Detector/Documents/GUIDENCE.md
T

30 KiB
Raw Blame History

探测器模块使用指南 | Detector Module Usage Guide

1. 模块概述 | Module Overview

XP.Hardware.Detector 是 XplorePlane X 射线检测系统的探测器控制模块,负责与工业 X 射线探测器进行通讯和控制。该模块采用策略模式设计,支持多种探测器型号的统一管理。

核心特性 | Key Features

  • 支持多种探测器型号(Varex、iRay 等)
  • 完整的探测器生命周期管理(初始化、采集、校正)
  • 单帧和连续采集模式
  • 自动校正功能(暗场、增益、坏像素)
  • 实时状态监控
  • 基于 Prism 事件聚合器的松耦合通讯
  • 异步操作,不阻塞 UI 线程

2. 模块注册 | Module Registration

探测器模块通过 Prism 的模块化系统注册,在应用启动时自动加载。

在 App.xaml.cs 中注册

using Prism.Modularity;
using XP.Hardware.Detector.Module;

protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog)
{
    // 注册探测器模块 | Register Detector module
    moduleCatalog.AddModule<DetectorModule>();
    
    base.ConfigureModuleCatalog(moduleCatalog);
}

模块自动注册的服务

  • IDetectorFactory - 探测器工厂(瞬态)
  • IDetectorService - 探测器业务服务(单例)

3. 配置文件设置 | Configuration File Setup

App.config 中添加探测器配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <!-- 探测器类型 | Detector Type -->
    <add key="Detector:Type" value="Varex" />
    
    <!-- 网络配置 | Network Configuration -->
    <add key="Detector:IP" value="192.168.1.200" />
    <add key="Detector:Port" value="50000" />
    
    <!-- 图像存储配置 | Image Storage Configuration -->
    <add key="Detector:SavePath" value="D:\Images" />
    <add key="Detector:AutoSave" value="true" />
    
    <!-- Varex 探测器特定配置 | Varex Detector Specific Configuration -->
    <add key="Varex:ConfigFile" value="detector.xml" />
    <add key="Varex:CalibrationFile" value="calibration.cal" />
    
    <!-- iRay 探测器特定配置 | iRay Detector Specific Configuration -->
    <add key="IRay:DeviceID" value="0" />
    <add key="IRay:ExposureTime" value="100" />
  </appSettings>
</configuration>

配置参数说明

参数 类型 默认值 说明
Type string Varex 探测器类型(Varex/IRay
IP string 192.168.1.200 探测器 IP 地址
Port int 50000 探测器端口号
SavePath string D:\Images 图像存储路径
AutoSave bool true 是否自动保存图像

4. 在 ViewModel 中使用 | Usage in ViewModel

4.1 注入服务

using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System.Threading.Tasks;
using XP.Common.Logging.Interfaces;
using XP.Hardware.Detector.Abstractions;
using XP.Hardware.Detector.Abstractions.Enums;
using XP.Hardware.Detector.Abstractions.Events;
using XP.Hardware.Detector.Services;

namespace YourNamespace.ViewModels
{
    public class YourViewModel : BindableBase
    {
        private readonly IDetectorService _detectorService;
        private readonly IEventAggregator _eventAggregator;
        private readonly ILoggerService _logger;

        /// <summary>
        /// 构造函数,通过依赖注入获取服务 | Constructor with dependency injection
        /// </summary>
        public YourViewModel(
            IDetectorService detectorService,
            IEventAggregator eventAggregator,
            ILoggerService logger)
        {
            _detectorService = detectorService;
            _eventAggregator = eventAggregator;
            _logger = logger.ForModule("YourViewModel");
            
            // 订阅事件 | Subscribe to events
            SubscribeEvents();
        }
        
        private void SubscribeEvents()
        {
            // 订阅图像采集事件 | Subscribe to image captured event
            _eventAggregator.GetEvent<ImageCapturedEvent>()
                .Subscribe(OnImageCaptured);
            
            // 订阅校正完成事件 | Subscribe to correction completed event
            _eventAggregator.GetEvent<CorrectionCompletedEvent>()
                .Subscribe(OnCorrectionCompleted);
        }
        
        private void OnImageCaptured(ImageCapturedEventArgs args)
        {
            _logger.Info($"图像已采集: {args.FrameNumber}");
        }
        
        private void OnCorrectionCompleted(CorrectionCompletedEventArgs args)
        {
            _logger.Info($"校正完成: {args.CorrectionType}");
        }
    }
}

4.2 初始化探测器

/// <summary>
/// 初始化探测器 | Initialize detector
/// </summary>
public async Task InitializeDetectorAsync()
{
    try
    {
        _logger.Info("开始初始化探测器... | Starting detector initialization...");
        StatusMessage = "正在初始化... | Initializing...";
        
        DetectorResult result = await _detectorService.InitializeAsync();
        
        if (result.IsSuccess)
        {
            _logger.Info("探测器初始化成功 | Detector initialized successfully");
            StatusMessage = "探测器已就绪 | Detector ready";
            
            // 获取探测器信息 | Get detector information
            DetectorInfo info = _detectorService.GetInfo();
            _logger.Info($"探测器型号: {info.Model}, 分辨率: {info.MaxWidth}x{info.MaxHeight}");
        }
        else
        {
            _logger.Error(null, $"探测器初始化失败: {result.ErrorMessage}");
            StatusMessage = $"初始化失败: {result.ErrorMessage}";
        }
    }
    catch (Exception ex)
    {
        _logger.Error(ex, $"初始化异常: {ex.Message}");
        StatusMessage = $"初始化异常: {ex.Message}";
    }
}

4.3 单帧采集

/// <summary>
/// 单帧采集 | Single frame acquisition
/// </summary>
public async Task AcquireSingleFrameAsync()
{
    try
    {
        if (_detectorService.Status != DetectorStatus.Ready)
        {
            _logger.Warn("探测器未就绪,无法采集");
            StatusMessage = "探测器未就绪 | Detector not ready";
            return;
        }
        
        _logger.Info("开始单帧采集... | Starting single frame acquisition...");
        StatusMessage = "正在采集... | Acquiring...";
        
        DetectorResult result = await _detectorService.AcquireSingleFrameAsync();
        
        if (result.IsSuccess)
        {
            _logger.Info("单帧采集成功 | Single frame acquired successfully");
            StatusMessage = "采集完成 | Acquisition completed";
        }
        else
        {
            _logger.Error(null, $"单帧采集失败: {result.ErrorMessage}");
            StatusMessage = $"采集失败: {result.ErrorMessage}";
        }
    }
    catch (Exception ex)
    {
        _logger.Error(ex, $"单帧采集异常: {ex.Message}");
        StatusMessage = $"采集异常: {ex.Message}";
    }
}

4.4 启动连续采集

/// <summary>
/// 启动连续采集 | Start continuous acquisition
/// </summary>
public async Task StartAcquisitionAsync()
{
    try
    {
        if (_detectorService.Status != DetectorStatus.Ready)
        {
            _logger.Warn("探测器未就绪,无法启动采集");
            return;
        }
        
        _logger.Info("启动连续采集... | Starting continuous acquisition...");
        StatusMessage = "连续采集中... | Continuous acquisition...";
        
        DetectorResult result = await _detectorService.StartAcquisitionAsync();
        
        if (result.IsSuccess)
        {
            _logger.Info("连续采集已启动 | Continuous acquisition started");
            IsAcquiring = true;
        }
        else
        {
            _logger.Error(null, $"启动采集失败: {result.ErrorMessage}");
            StatusMessage = $"启动失败: {result.ErrorMessage}";
        }
    }
    catch (Exception ex)
    {
        _logger.Error(ex, $"启动采集异常: {ex.Message}");
        StatusMessage = $"启动异常: {ex.Message}";
    }
}

4.5 停止采集

/// <summary>
/// 停止采集 | Stop acquisition
/// </summary>
public async Task StopAcquisitionAsync()
{
    try
    {
        _logger.Info("停止采集... | Stopping acquisition...");
        StatusMessage = "正在停止... | Stopping...";
        
        DetectorResult result = await _detectorService.StopAcquisitionAsync();
        
        if (result.IsSuccess)
        {
            _logger.Info("采集已停止 | Acquisition stopped");
            StatusMessage = "已停止 | Stopped";
            IsAcquiring = false;
        }
        else
        {
            _logger.Error(null, $"停止采集失败: {result.ErrorMessage}");
            StatusMessage = $"停止失败: {result.ErrorMessage}";
        }
    }
    catch (Exception ex)
    {
        _logger.Error(ex, $"停止采集异常: {ex.Message}");
        StatusMessage = $"停止异常: {ex.Message}";
    }
}

5. 校正功能 | Correction Functions

5.1 自动校正

/// <summary>
/// 执行自动校正(暗场+增益+坏像素)| Execute auto correction (dark + gain + bad pixel)
/// </summary>
/// <param name="frameCount">采集帧数 | Frame count</param>
public async Task AutoCorrectionAsync(int frameCount = 10)
{
    try
    {
        _logger.Info($"开始自动校正,帧数: {frameCount} | Starting auto correction, frames: {frameCount}");
        StatusMessage = "正在校正... | Correcting...";
        
        DetectorResult result = await _detectorService.AutoCorrectionAsync(frameCount);
        
        if (result.IsSuccess)
        {
            _logger.Info("自动校正完成 | Auto correction completed");
            StatusMessage = "校正完成 | Correction completed";
        }
        else
        {
            _logger.Error(null, $"自动校正失败: {result.ErrorMessage}");
            StatusMessage = $"校正失败: {result.ErrorMessage}";
        }
    }
    catch (Exception ex)
    {
        _logger.Error(ex, $"自动校正异常: {ex.Message}");
        StatusMessage = $"校正异常: {ex.Message}";
    }
}

5.2 获取探测器信息

/// <summary>
/// 获取探测器信息 | Get detector information
/// </summary>
public void GetDetectorInfo()
{
    try
    {
        DetectorInfo info = _detectorService.GetInfo();
        
        if (info != null)
        {
            _logger.Info($"探测器信息:");
            _logger.Info($"  型号: {info.Model}");
            _logger.Info($"  序列号: {info.SerialNumber}");
            _logger.Info($"  固件版本: {info.FirmwareVersion}");
            _logger.Info($"  分辨率: {info.MaxWidth}x{info.MaxHeight}");
            _logger.Info($"  像素尺寸: {info.PixelSize}μm");
            _logger.Info($"  位深度: {info.BitDepth}bit");
            
            // 更新 UI 显示 | Update UI display
            DetectorModel = info.Model;
            Resolution = $"{info.MaxWidth}x{info.MaxHeight}";
            PixelSize = $"{info.PixelSize}μm";
        }
    }
    catch (Exception ex)
    {
        _logger.Error(ex, $"获取探测器信息异常: {ex.Message}");
    }
}

6. Prism 事件通讯 | Prism Event Communication

模块使用 Prism 事件聚合器实现跨模块通讯,支持以下事件:

6.1 图像采集事件

// 订阅图像采集事件 | Subscribe to image captured event
_eventAggregator.GetEvent<ImageCapturedEvent>()
    .Subscribe(OnImageCaptured, ThreadOption.UIThread);

private void OnImageCaptured(ImageCapturedEventArgs args)
{
    // args.FrameNumber - 帧编号
    // args.Timestamp - 时间戳
    // args.ImageData - 图像数据(如果有)
    
    FrameNumber = args.FrameNumber;
    LastCaptureTime = args.Timestamp;
    
    _logger.Info($"图像已采集: 帧 {args.FrameNumber}");
}

6.2 校正完成事件

// 订阅校正完成事件 | Subscribe to correction completed event
_eventAggregator.GetEvent<CorrectionCompletedEvent>()
    .Subscribe(OnCorrectionCompleted, ThreadOption.UIThread);

private void OnCorrectionCompleted(CorrectionCompletedEventArgs args)
{
    // args.CorrectionType - 校正类型(暗场/增益/坏像素)
    // args.IsSuccess - 是否成功
    // args.Message - 消息
    
    if (args.IsSuccess)
    {
        _logger.Info($"校正完成: {args.CorrectionType}");
        StatusMessage = $"{args.CorrectionType} 校正完成";
    }
    else
    {
        _logger.Error(null, $"校正失败: {args.Message}");
        StatusMessage = $"校正失败: {args.Message}";
    }
}

7. 完整示例 | Complete Example

using Prism.Commands;
using Prism.Events;
using Prism.Mvvm;
using System;
using System.Threading.Tasks;
using System.Windows.Input;
using XP.Common.Logging.Interfaces;
using XP.Hardware.Detector.Abstractions;
using XP.Hardware.Detector.Abstractions.Enums;
using XP.Hardware.Detector.Abstractions.Events;
using XP.Hardware.Detector.Services;

namespace YourNamespace.ViewModels
{
    public class DetectorControlViewModel : BindableBase
    {
        private readonly IDetectorService _detectorService;
        private readonly IEventAggregator _eventAggregator;
        private readonly ILoggerService _logger;

        #region 属性 | Properties

        private string _statusMessage;
        public string StatusMessage
        {
            get => _statusMessage;
            set => SetProperty(ref _statusMessage, value);
        }

        private DetectorStatus _detectorStatus;
        public DetectorStatus DetectorStatus
        {
            get => _detectorStatus;
            set => SetProperty(ref _detectorStatus, value);
        }

        private bool _isAcquiring;
        public bool IsAcquiring
        {
            get => _isAcquiring;
            set => SetProperty(ref _isAcquiring, value);
        }

        private int _frameNumber;
        public int FrameNumber
        {
            get => _frameNumber;
            set => SetProperty(ref _frameNumber, value);
        }

        private string _detectorModel;
        public string DetectorModel
        {
            get => _detectorModel;
            set => SetProperty(ref _detectorModel, value);
        }

        private string _resolution;
        public string Resolution
        {
            get => _resolution;
            set => SetProperty(ref _resolution, value);
        }

        #endregion

        #region 命令 | Commands

        public ICommand InitializeCommand { get; }
        public ICommand AcquireSingleFrameCommand { get; }
        public ICommand StartAcquisitionCommand { get; }
        public ICommand StopAcquisitionCommand { get; }
        public ICommand AutoCorrectionCommand { get; }
        public ICommand GetInfoCommand { get; }

        #endregion

        public DetectorControlViewModel(
            IDetectorService detectorService,
            IEventAggregator eventAggregator,
            ILoggerService logger)
        {
            _detectorService = detectorService;
            _eventAggregator = eventAggregator;
            _logger = logger.ForModule("DetectorControlViewModel");

            // 初始化命令 | Initialize commands
            InitializeCommand = new DelegateCommand(async () => await InitializeAsync());
            AcquireSingleFrameCommand = new DelegateCommand(async () => await AcquireSingleFrameAsync(), CanAcquire)
                .ObservesProperty(() => DetectorStatus);
            StartAcquisitionCommand = new DelegateCommand(async () => await StartAcquisitionAsync(), CanStartAcquisition)
                .ObservesProperty(() => DetectorStatus)
                .ObservesProperty(() => IsAcquiring);
            StopAcquisitionCommand = new DelegateCommand(async () => await StopAcquisitionAsync(), CanStopAcquisition)
                .ObservesProperty(() => IsAcquiring);
            AutoCorrectionCommand = new DelegateCommand(async () => await AutoCorrectionAsync(), CanCorrect)
                .ObservesProperty(() => DetectorStatus);
            GetInfoCommand = new DelegateCommand(GetInfo);

            // 订阅事件 | Subscribe to events
            SubscribeEvents();
        }

        #region 命令实现 | Command Implementations

        private async Task InitializeAsync()
        {
            try
            {
                StatusMessage = "正在初始化... | Initializing...";
                DetectorResult result = await _detectorService.InitializeAsync();
                
                if (result.IsSuccess)
                {
                    DetectorStatus = _detectorService.Status;
                    StatusMessage = "探测器已就绪 | Detector ready";
                    GetInfo();
                }
                else
                {
                    StatusMessage = $"初始化失败: {result.ErrorMessage}";
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "初始化异常");
                StatusMessage = $"初始化异常: {ex.Message}";
            }
        }

        private async Task AcquireSingleFrameAsync()
        {
            try
            {
                StatusMessage = "正在采集... | Acquiring...";
                DetectorResult result = await _detectorService.AcquireSingleFrameAsync();
                
                if (result.IsSuccess)
                {
                    StatusMessage = "采集完成 | Acquisition completed";
                }
                else
                {
                    StatusMessage = $"采集失败: {result.ErrorMessage}";
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "单帧采集异常");
                StatusMessage = $"采集异常: {ex.Message}";
            }
        }

        private async Task StartAcquisitionAsync()
        {
            try
            {
                StatusMessage = "启动连续采集... | Starting continuous acquisition...";
                DetectorResult result = await _detectorService.StartAcquisitionAsync();
                
                if (result.IsSuccess)
                {
                    IsAcquiring = true;
                    DetectorStatus = _detectorService.Status;
                    StatusMessage = "连续采集中... | Continuous acquisition...";
                }
                else
                {
                    StatusMessage = $"启动失败: {result.ErrorMessage}";
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "启动采集异常");
                StatusMessage = $"启动异常: {ex.Message}";
            }
        }

        private async Task StopAcquisitionAsync()
        {
            try
            {
                StatusMessage = "正在停止... | Stopping...";
                DetectorResult result = await _detectorService.StopAcquisitionAsync();
                
                if (result.IsSuccess)
                {
                    IsAcquiring = false;
                    DetectorStatus = _detectorService.Status;
                    StatusMessage = "已停止 | Stopped";
                }
                else
                {
                    StatusMessage = $"停止失败: {result.ErrorMessage}";
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "停止采集异常");
                StatusMessage = $"停止异常: {ex.Message}";
            }
        }

        private async Task AutoCorrectionAsync()
        {
            try
            {
                StatusMessage = "正在校正... | Correcting...";
                DetectorResult result = await _detectorService.AutoCorrectionAsync(10);
                
                if (result.IsSuccess)
                {
                    StatusMessage = "校正完成 | Correction completed";
                }
                else
                {
                    StatusMessage = $"校正失败: {result.ErrorMessage}";
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "自动校正异常");
                StatusMessage = $"校正异常: {ex.Message}";
            }
        }

        private void GetInfo()
        {
            try
            {
                DetectorInfo info = _detectorService.GetInfo();
                if (info != null)
                {
                    DetectorModel = info.Model;
                    Resolution = $"{info.MaxWidth}x{info.MaxHeight}";
                }
            }
            catch (Exception ex)
            {
                _logger.Error(ex, "获取信息异常");
            }
        }

        #endregion

        #region 命令条件 | Command Conditions

        private bool CanAcquire() => DetectorStatus == DetectorStatus.Ready;
        private bool CanStartAcquisition() => DetectorStatus == DetectorStatus.Ready && !IsAcquiring;
        private bool CanStopAcquisition() => IsAcquiring;
        private bool CanCorrect() => DetectorStatus == DetectorStatus.Ready;

        #endregion

        #region 事件处理 | Event Handlers

        private void SubscribeEvents()
        {
            _eventAggregator.GetEvent<ImageCapturedEvent>()
                .Subscribe(OnImageCaptured, ThreadOption.UIThread);
            
            _eventAggregator.GetEvent<CorrectionCompletedEvent>()
                .Subscribe(OnCorrectionCompleted, ThreadOption.UIThread);
        }

        private void OnImageCaptured(ImageCapturedEventArgs args)
        {
            FrameNumber = args.FrameNumber;
        }

        private void OnCorrectionCompleted(CorrectionCompletedEventArgs args)
        {
            if (args.IsSuccess)
            {
                StatusMessage = $"{args.CorrectionType} 校正完成";
            }
        }

        #endregion
    }
}

8. 在应用退出时释放资源 | Release Resources on Application Exit

App.xaml.csOnExit 方法中添加:

protected override void OnExit(ExitEventArgs e)
{
    // 记录应用退出日志 | Log application exit
    Log.Information("XplorePlane主应用退出(XP.App-OnExit");

    // 释放探测器资源 | Release detector resources
    try
    {
        var detectorService = Container.Resolve<IDetectorService>();
        // 探测器服务会在 Dispose 时自动停止采集和释放资源
        // Detector service will automatically stop acquisition and release resources on Dispose
        Log.Information("探测器资源已成功释放 | Detector resources released successfully");
    }
    catch (Exception ex)
    {
        Log.Error(ex, "探测器资源释放失败,忽略该错误继续退出 | Failed to release detector resources");
    }

    // 释放其他资源... | Release other resources...
    
    // 释放Serilog资源(避免日志丢失)| Release Serilog resources
    Log.CloseAndFlush();

    base.OnExit(e);
}

9. 探测器状态 | Detector Status

9.1 状态枚举

public enum DetectorStatus
{
    Uninitialized = 0,  // 未初始化
    Initializing = 1,   // 初始化中
    Ready = 2,          // 就绪
    Acquiring = 3,      // 采集中
    Correcting = 4,     // 校正中
    Error = 5           // 错误
}

9.2 状态监控

// 监控探测器状态变化 | Monitor detector status changes
private void MonitorStatus()
{
    DetectorStatus currentStatus = _detectorService.Status;
    
    switch (currentStatus)
    {
        case DetectorStatus.Uninitialized:
            StatusMessage = "未初始化 | Uninitialized";
            break;
        case DetectorStatus.Initializing:
            StatusMessage = "初始化中... | Initializing...";
            break;
        case DetectorStatus.Ready:
            StatusMessage = "就绪 | Ready";
            break;
        case DetectorStatus.Acquiring:
            StatusMessage = "采集中... | Acquiring...";
            break;
        case DetectorStatus.Correcting:
            StatusMessage = "校正中... | Correcting...";
            break;
        case DetectorStatus.Error:
            StatusMessage = "错误 | Error";
            // 获取错误信息 | Get error information
            DetectorResult error = _detectorService.GetLastError();
            _logger.Error(null, $"探测器错误: {error.ErrorMessage}");
            break;
    }
}

10. 异常处理 | Exception Handling

10.1 DetectorResult 结果处理

所有操作返回 DetectorResult 对象:

DetectorResult result = await _detectorService.InitializeAsync();

if (result.IsSuccess)
{
    // 操作成功 | Operation successful
    _logger.Info("操作成功");
}
else
{
    // 操作失败 | Operation failed
    string error = result.ErrorMessage;
    int errorCode = result.ErrorCode;
    Exception exception = result.Exception;
    
    _logger.Error(exception, $"操作失败: {error}, 错误码: {errorCode}");
}

10.2 异常捕获

try
{
    DetectorResult result = await _detectorService.AcquireSingleFrameAsync();
    // 处理结果 | Process result
}
catch (TimeoutException ex)
{
    // 超时异常 | Timeout exception
    _logger.Error(ex, "操作超时");
    MessageBox.Show("操作超时,请检查探测器连接", "超时", 
        MessageBoxButton.OK, MessageBoxImage.Warning);
}
catch (InvalidOperationException ex)
{
    // 无效操作异常 | Invalid operation exception
    _logger.Error(ex, "无效操作");
    MessageBox.Show($"无效操作: {ex.Message}", "错误", 
        MessageBoxButton.OK, MessageBoxImage.Error);
}
catch (Exception ex)
{
    // 其他异常 | Other exceptions
    _logger.Error(ex, "未知错误");
    MessageBox.Show($"发生错误: {ex.Message}", "错误", 
        MessageBoxButton.OK, MessageBoxImage.Error);
}

11. 日志记录 | Logging

模块使用 Serilog 进行结构化日志记录:

11.1 日志级别

  • Debug: 详细的调试信息(帧采集、状态变化等)
  • Info: 一般信息(初始化成功、采集开始等)
  • Warn: 警告信息(状态异常、参数警告等)
  • Error: 错误信息(操作失败、通讯异常等)
  • Fatal: 致命错误(系统崩溃等)

11.2 日志示例

// 信息日志 | Info log
_logger.Info("探测器初始化成功 | Detector initialized successfully");

// 警告日志 | Warning log
_logger.Warn("探测器未就绪 | Detector not ready");

// 错误日志 | Error log
_logger.Error(ex, $"操作失败: {ex.Message} | Operation failed: {ex.Message}");

// 调试日志 | Debug log
_logger.Debug($"采集帧 {frameNumber} | Acquired frame {frameNumber}");

12. 性能优化建议 | Performance Optimization Suggestions

12.1 图像处理

避免在 UI 线程处理大图像:

// 推荐:在后台线程处理图像 | Recommended: Process images in background thread
await Task.Run(() =>
{
    // 图像处理逻辑 | Image processing logic
    ProcessImage(imageData);
});

12.2 异步操作

所有 I/O 操作使用异步方法:

// 正确:异步操作 | Correct: Async operation
await _detectorService.AcquireSingleFrameAsync();

// 错误:同步阻塞 | Wrong: Synchronous blocking
_detectorService.AcquireSingleFrameAsync().Wait(); // 不要这样做!

12.3 事件订阅

及时取消不再需要的事件订阅:

// 保存订阅令牌 | Save subscription token
private SubscriptionToken _imageCapturedToken;

// 订阅事件 | Subscribe to event
_imageCapturedToken = _eventAggregator.GetEvent<ImageCapturedEvent>()
    .Subscribe(OnImageCaptured, ThreadOption.UIThread);

// 取消订阅 | Unsubscribe
_eventAggregator.GetEvent<ImageCapturedEvent>()
    .Unsubscribe(_imageCapturedToken);

13. 故障排查 | Troubleshooting

13.1 初始化失败

问题: 探测器初始化失败

可能原因:

  • 探测器 IP 地址或端口配置错误
  • 探测器未启动或网络不通
  • 探测器驱动未正确安装
  • 配置文件参数错误

解决方案:

  1. 检查 App.config 中的探测器连接参数
  2. 使用 ping 命令测试探测器网络连接
  3. 确认探测器驱动和 SDK 已安装
  4. 查看日志文件获取详细错误信息

13.2 采集失败

问题: 无法采集图像

可能原因:

  • 探测器未初始化
  • 探测器处于错误状态
  • 校正未完成
  • 网络通讯异常

解决方案:

  1. 确认已调用 InitializeAsync() 并成功
  2. 检查探测器状态是否为 Ready
  3. 执行自动校正 AutoCorrectionAsync()
  4. 检查网络连接和通讯日志

13.3 校正失败

问题: 校正操作失败

可能原因:

  • 探测器未就绪
  • 射线源未开启(增益校正需要)
  • 采集帧数不足
  • 环境光干扰

解决方案:

  1. 确认探测器状态为 Ready
  2. 增益校正前确保射线源已开启
  3. 增加采集帧数(建议 10 帧以上)
  4. 检查暗场环境,避免光线干扰

13.4 通讯超时

问题: 操作超时

可能原因:

  • 网络延迟过高
  • 探测器响应慢
  • 超时配置过短

解决方案:

  1. 检查网络连接质量
  2. 增加配置文件中的超时时间
  3. 检查探测器负载情况

14. 注意事项 | Notes

  1. 线程安全: IDetectorService 是单例,多个 ViewModel 共享同一个实例
  2. 异步操作: 所有操作都是异步的,避免阻塞 UI 线程
  3. 状态检查: 操作前检查探测器状态,确保处于正确状态
  4. 资源释放: 应用退出时探测器会自动停止采集并释放资源
  5. 事件订阅: 记得在 ViewModel 销毁时取消事件订阅
  6. 校正顺序: 建议按照暗场→增益→坏像素的顺序进行校正
  7. 日志记录: 所有关键操作都有详细的日志记录
  8. 错误处理: 始终检查 DetectorResult.IsSuccess 并处理错误

15. 文档索引 | Documentation Index


16. 技术支持 | Technical Support

如有问题或建议,请联系项目维护团队。


最后更新 | Last Updated: 2026-03-11