Files
XplorePlane/XP.Hardware.Detector/Services/DetectorService.cs
T
QI Mingxuan 2d7cf17a3b 探测器XP.Hardware.Detector类库为了更好集成新的探测器,统一接口方法,DetectorService重构为通过统一接口;
新增暗场校正和亮场校正帧数配置属性(默认 64,范围 1-128),config 加载校正帧数;
修正探测器IsConnected连接状态的判断逻辑。
2026-05-21 13:19:30 +08:00

759 lines
35 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 System;
using System.Threading;
using System.Threading.Tasks;
using Prism.Events;
using XP.Hardware.Detector.Abstractions;
using XP.Hardware.Detector.Abstractions.Enums;
using XP.Hardware.Detector.Config;
using XP.Hardware.Detector.Factories;
using XP.Common.Logging.Interfaces;
namespace XP.Hardware.Detector.Services
{
/// <summary>
/// 探测器服务实现 | Detector service implementation
/// 单例模式,封装业务逻辑,屏蔽厂商差异
/// </summary>
public class DetectorService : IDetectorService, IDisposable
{
private readonly IDetectorFactory _factory;
private readonly IEventAggregator _eventAggregator;
private readonly ILoggerService _logger;
private readonly object _lock = new object();
private IAreaDetector _detector;
private DetectorConfig _config;
private DetectorResult _lastError;
private bool _disposed = false;
/// <summary>
/// 当前探测器状态 | Current detector status
/// </summary>
public DetectorStatus Status
{
get
{
lock (_lock)
{
return _detector?.Status ?? DetectorStatus.Uninitialized;
}
}
}
/// <summary>
/// 当前探测器类型 | Current detector type
/// </summary>
public DetectorType? Type
{
get
{
lock (_lock)
{
return _detector?.Type;
}
}
}
/// <summary>
/// 探测器是否已连接 | Whether detector is connected
/// </summary>
public bool IsConnected
{
get
{
lock (_lock)
{
if (_detector == null) return false;
var status = _detector.Status;
return status == DetectorStatus.Ready
|| status == DetectorStatus.Acquiring
|| status == DetectorStatus.Correcting;
}
}
}
/// <summary>
/// 构造函数 | Constructor
/// </summary>
/// <param name="factory">探测器工厂 | Detector factory</param>
/// <param name="eventAggregator">事件聚合器 | Event aggregator</param>
/// <param name="logger">日志服务 | Logger service</param>
public DetectorService(IDetectorFactory factory, IEventAggregator eventAggregator, ILoggerService logger = null)
{
_factory = factory ?? throw new ArgumentNullException(nameof(factory));
_eventAggregator = eventAggregator ?? throw new ArgumentNullException(nameof(eventAggregator));
_logger = logger?.ForModule("DetectorService");
_logger?.Info("DetectorService 实例已创建 | DetectorService instance created");
}
/// <summary>
/// 初始化探测器 | Initialize detector
/// </summary>
/// <param name="cancellationToken">取消令牌 | Cancellation token</param>
/// <returns>操作结果 | Operation result</returns>
public async Task<DetectorResult> InitializeAsync(CancellationToken cancellationToken = default)
{
// 若已连接,先断开再重连 | If already connected, disconnect first then reconnect
bool alreadyConnected;
lock (_lock) { alreadyConnected = _detector != null; }
if (alreadyConnected)
{
_logger?.Info("探测器已连接,先断开再重新初始化 | Detector already connected, disconnecting before reinitializing");
await DisconnectAsync();
}
try
{
_logger?.Info("开始初始化探测器服务 | Starting to initialize detector service");
// 加载配置 | Load configuration
_logger?.Debug("加载配置文件 | Loading configuration file");
var configResult = ConfigLoader.LoadConfiguration();
if (!configResult.IsSuccess)
{
_lastError = configResult;
_logger?.Error(null, $"加载配置失败 | Failed to load configuration: {configResult.ErrorMessage}");
return configResult;
}
_logger?.Info($"配置加载成功,探测器类型:{configResult.Data.Type} | Configuration loaded successfully, detector type: {configResult.Data.Type}");
// 保存配置引用 | Save config reference
_config = configResult.Data;
// 创建探测器实例 | Create detector instance
_logger?.Debug("创建探测器实例 | Creating detector instance");
var createResult = _factory.CreateDetector(configResult.Data);
if (!createResult.IsSuccess)
{
_lastError = createResult;
_logger?.Error(createResult.Exception, $"创建探测器实例失败 | Failed to create detector instance: {createResult.ErrorMessage}");
return DetectorResult.Failure(createResult.ErrorMessage, createResult.Exception, createResult.ErrorCode);
}
lock (_lock)
{
_detector = createResult.Data;
}
// 初始化探测器 | Initialize detector
_logger?.Debug("初始化探测器硬件 | Initializing detector hardware");
var initResult = await _detector.InitializeAsync(cancellationToken);
if (!initResult.IsSuccess)
{
_lastError = initResult;
_logger?.Error(initResult.Exception, $"初始化探测器硬件失败 | Failed to initialize detector hardware: {initResult.ErrorMessage}");
}
else
{
_logger?.Info("探测器服务初始化成功 | Detector service initialized successfully");
}
return initResult;
}
catch (Exception ex)
{
var errorMsg = $"初始化服务失败 | Failed to initialize service: {ex.Message}";
_logger?.Error(ex, errorMsg);
var errorResult = DetectorResult.Failure(errorMsg, ex, -1);
_lastError = errorResult;
return errorResult;
}
}
/// <summary>
/// 断开探测器连接 | Disconnect detector
/// </summary>
public async Task<DetectorResult> DisconnectAsync()
{
try
{
IAreaDetector detector;
lock (_lock)
{
detector = _detector;
if (detector == null)
{
_logger?.Warn("探测器未连接,无需断开 | Detector not connected, no need to disconnect");
return DetectorResult.Success("探测器未连接 | Detector not connected");
}
}
_logger?.Info("开始断开探测器连接 | Starting to disconnect detector");
// 如果正在采集,先停止 | If acquiring, stop first
if (detector.Status == DetectorStatus.Acquiring)
{
_logger?.Info("探测器正在采集,先停止采集 | Detector is acquiring, stopping first");
await detector.StopAcquisitionAsync();
}
// 释放探测器资源 | Dispose detector resources
lock (_lock)
{
_detector?.Dispose();
_detector = null;
}
_config = null;
_logger?.Info("探测器已断开连接 | Detector disconnected");
return DetectorResult.Success("探测器已断开连接 | Detector disconnected");
}
catch (Exception ex)
{
var errorMsg = $"断开探测器连接异常 | Disconnect detector exception: {ex.Message}";
_logger?.Error(ex, errorMsg);
// 强制清理 | Force cleanup
lock (_lock)
{
_detector?.Dispose();
_detector = null;
}
_config = null;
var errorResult = DetectorResult.Failure(errorMsg, ex, -1);
_lastError = errorResult;
return errorResult;
}
}
/// <summary>
/// 启动连续采集 | Start continuous acquisition
/// </summary>
/// <param name="cancellationToken">取消令牌 | Cancellation token</param>
/// <returns>操作结果 | Operation result</returns>
public async Task<DetectorResult> StartAcquisitionAsync(CancellationToken cancellationToken = default)
{
try
{
_logger?.Info("服务层:启动连续采集 | Service layer: Starting continuous acquisition");
var detector = GetDetectorOrThrow();
var result = await detector.StartAcquisitionAsync(cancellationToken);
if (!result.IsSuccess)
{
_lastError = result;
_logger?.Error(result.Exception, $"启动采集失败 | Failed to start acquisition: {result.ErrorMessage}");
}
return result;
}
catch (Exception ex)
{
var errorMsg = $"服务层启动采集异常 | Service layer start acquisition exception: {ex.Message}";
_logger?.Error(ex, errorMsg);
var errorResult = DetectorResult.Failure(errorMsg, ex, -1);
_lastError = errorResult;
return errorResult;
}
}
/// <summary>
/// 停止采集 | Stop acquisition
/// </summary>
/// <param name="cancellationToken">取消令牌 | Cancellation token</param>
/// <returns>操作结果 | Operation result</returns>
public async Task<DetectorResult> StopAcquisitionAsync(CancellationToken cancellationToken = default)
{
try
{
_logger?.Info("服务层:停止采集 | Service layer: Stopping acquisition");
var detector = GetDetectorOrThrow();
var result = await detector.StopAcquisitionAsync(cancellationToken);
if (!result.IsSuccess)
{
_lastError = result;
_logger?.Error(result.Exception, $"停止采集失败 | Failed to stop acquisition: {result.ErrorMessage}");
}
return result;
}
catch (Exception ex)
{
var errorMsg = $"服务层停止采集异常 | Service layer stop acquisition exception: {ex.Message}";
_logger?.Error(ex, errorMsg);
var errorResult = DetectorResult.Failure(errorMsg, ex, -1);
_lastError = errorResult;
return errorResult;
}
}
/// <summary>
/// 单帧采集 | Single frame acquisition
/// </summary>
/// <param name="cancellationToken">取消令牌 | Cancellation token</param>
/// <returns>操作结果 | Operation result</returns>
public async Task<DetectorResult> AcquireSingleFrameAsync(CancellationToken cancellationToken = default)
{
try
{
_logger?.Debug("服务层:单帧采集 | Service layer: Single frame acquisition");
var detector = GetDetectorOrThrow();
var result = await detector.AcquireSingleFrameAsync(cancellationToken);
if (!result.IsSuccess)
{
_lastError = result;
_logger?.Error(result.Exception, $"单帧采集失败 | Failed to acquire single frame: {result.ErrorMessage}");
}
return result;
}
catch (Exception ex)
{
var errorMsg = $"服务层单帧采集异常 | Service layer single frame acquisition exception: {ex.Message}";
_logger?.Error(ex, errorMsg);
var errorResult = DetectorResult.Failure(errorMsg, ex, -1);
_lastError = errorResult;
return errorResult;
}
}
/// <summary>
/// 暗场校正 | Dark field correction
/// </summary>
/// <param name="frameCount">采集帧数 | Frame count</param>
/// <param name="cancellationToken">取消令牌 | Cancellation token</param>
/// <returns>操作结果 | Operation result</returns>
public async Task<DetectorResult> DarkCorrectionAsync(int frameCount = 10, CancellationToken cancellationToken = default)
{
try
{
_logger?.Info("服务层:执行暗场校正,帧数:{FrameCount} | Service layer: Executing dark correction, frame count: {FrameCount}", frameCount);
var detector = GetDetectorOrThrow();
// 如果正在采集,先停止(XISL SDK 不允许采集中执行校正)| Stop acquisition first if running
bool wasAcquiring = detector.Status == DetectorStatus.Acquiring;
if (wasAcquiring)
{
_logger?.Info("探测器正在采集,先停止采集再执行暗场校正 | Detector is acquiring, stopping before dark correction");
var stopResult = await detector.StopAcquisitionAsync(cancellationToken);
if (!stopResult.IsSuccess)
{
_lastError = stopResult;
_logger?.Error(stopResult.Exception, "停止采集失败,无法执行暗场校正:{Message} | Failed to stop acquisition, cannot perform dark correction: {Message}", stopResult.ErrorMessage);
return DetectorResult.Failure($"停止采集失败,无法执行暗场校正 | Failed to stop acquisition: {stopResult.ErrorMessage}");
}
}
var result = await detector.DarkCorrectionAsync(frameCount, cancellationToken);
if (!result.IsSuccess)
{
_lastError = result;
_logger?.Error(result.Exception, "暗场校正失败:{Message} | Dark correction failed: {Message}", result.ErrorMessage);
}
// 如果之前在采集,恢复采集 | Resume acquisition if it was running before
if (wasAcquiring)
{
_logger?.Info("暗场校正完成,恢复连续采集 | Dark correction done, resuming continuous acquisition");
var startResult = await detector.StartAcquisitionAsync(cancellationToken);
if (!startResult.IsSuccess)
{
_logger?.Warn("恢复采集失败:{Message} | Failed to resume acquisition: {Message}", startResult.ErrorMessage);
}
}
return result;
}
catch (Exception ex)
{
var errorMsg = $"服务层暗场校正异常 | Service layer dark correction exception: {ex.Message}";
_logger?.Error(ex, errorMsg);
var errorResult = DetectorResult.Failure(errorMsg, ex, -1);
_lastError = errorResult;
return errorResult;
}
}
/// <summary>
/// 增益校正(亮场校正)| Gain correction (bright field correction)
/// </summary>
/// <param name="frameCount">采集帧数 | Frame count</param>
/// <param name="cancellationToken">取消令牌 | Cancellation token</param>
/// <returns>操作结果 | Operation result</returns>
public async Task<DetectorResult> GainCorrectionAsync(int frameCount = 10, CancellationToken cancellationToken = default)
{
try
{
_logger?.Info("服务层:执行亮场校正,帧数:{FrameCount} | Service layer: Executing gain correction, frame count: {FrameCount}", frameCount);
var detector = GetDetectorOrThrow();
// 如果正在采集,先停止(XISL SDK 不允许采集中执行校正)| Stop acquisition first if running
bool wasAcquiring = detector.Status == DetectorStatus.Acquiring;
if (wasAcquiring)
{
_logger?.Info("探测器正在采集,先停止采集再执行亮场校正 | Detector is acquiring, stopping before gain correction");
var stopResult = await detector.StopAcquisitionAsync(cancellationToken);
if (!stopResult.IsSuccess)
{
_lastError = stopResult;
_logger?.Error(stopResult.Exception, "停止采集失败,无法执行亮场校正:{Message} | Failed to stop acquisition, cannot perform gain correction: {Message}", stopResult.ErrorMessage);
return DetectorResult.Failure($"停止采集失败,无法执行亮场校正 | Failed to stop acquisition: {stopResult.ErrorMessage}");
}
}
var result = await detector.GainCorrectionAsync(frameCount, cancellationToken);
if (!result.IsSuccess)
{
_lastError = result;
_logger?.Error(result.Exception, "亮场校正失败:{Message} | Gain correction failed: {Message}", result.ErrorMessage);
}
// 如果之前在采集,恢复采集 | Resume acquisition if it was running before
if (wasAcquiring)
{
_logger?.Info("亮场校正完成,恢复连续采集 | Gain correction done, resuming continuous acquisition");
var startResult = await detector.StartAcquisitionAsync(cancellationToken);
if (!startResult.IsSuccess)
{
_logger?.Warn("恢复采集失败:{Message} | Failed to resume acquisition: {Message}", startResult.ErrorMessage);
}
}
return result;
}
catch (Exception ex)
{
var errorMsg = $"服务层亮场校正异常 | Service layer gain correction exception: {ex.Message}";
_logger?.Error(ex, errorMsg);
var errorResult = DetectorResult.Failure(errorMsg, ex, -1);
_lastError = errorResult;
return errorResult;
}
}
/// <summary>
/// 坏像素校正 | Bad pixel correction
/// </summary>
/// <param name="cancellationToken">取消令牌 | Cancellation token</param>
/// <returns>操作结果 | Operation result</returns>
public async Task<DetectorResult> BadPixelCorrectionAsync(CancellationToken cancellationToken = default)
{
try
{
_logger?.Info("服务层:执行坏像素校正 | Service layer: Executing bad pixel correction");
var detector = GetDetectorOrThrow();
// 如果正在采集,先停止(XISL SDK 不允许采集中执行校正)| Stop acquisition first if running
bool wasAcquiring = detector.Status == DetectorStatus.Acquiring;
if (wasAcquiring)
{
_logger?.Info("探测器正在采集,先停止采集再执行坏像素校正 | Detector is acquiring, stopping before bad pixel correction");
var stopResult = await detector.StopAcquisitionAsync(cancellationToken);
if (!stopResult.IsSuccess)
{
_lastError = stopResult;
_logger?.Error(stopResult.Exception, "停止采集失败,无法执行坏像素校正:{Message} | Failed to stop acquisition, cannot perform bad pixel correction: {Message}", stopResult.ErrorMessage);
return DetectorResult.Failure($"停止采集失败,无法执行坏像素校正 | Failed to stop acquisition: {stopResult.ErrorMessage}");
}
}
var result = await detector.BadPixelCorrectionAsync(cancellationToken);
if (!result.IsSuccess)
{
_lastError = result;
_logger?.Error(result.Exception, "坏像素校正失败:{Message} | Bad pixel correction failed: {Message}", result.ErrorMessage);
}
// 如果之前在采集,恢复采集 | Resume acquisition if it was running before
if (wasAcquiring)
{
_logger?.Info("坏像素校正完成,恢复连续采集 | Bad pixel correction done, resuming continuous acquisition");
var startResult = await detector.StartAcquisitionAsync(cancellationToken);
if (!startResult.IsSuccess)
{
_logger?.Warn("恢复采集失败:{Message} | Failed to resume acquisition: {Message}", startResult.ErrorMessage);
}
}
return result;
}
catch (Exception ex)
{
var errorMsg = $"服务层坏像素校正异常 | Service layer bad pixel correction exception: {ex.Message}";
_logger?.Error(ex, errorMsg);
var errorResult = DetectorResult.Failure(errorMsg, ex, -1);
_lastError = errorResult;
return errorResult;
}
}
/// <summary>
/// 执行自动校正(暗场+增益+坏像素)| Execute auto correction (dark + gain + bad pixel)
/// </summary>
/// <param name="frameCount">采集帧数 | Frame count</param>
/// <param name="cancellationToken">取消令牌 | Cancellation token</param>
/// <returns>操作结果 | Operation result</returns>
public async Task<DetectorResult> AutoCorrectionAsync(int frameCount = 10, CancellationToken cancellationToken = default)
{
try
{
_logger?.Info("服务层:执行自动校正,帧数:{FrameCount} | Service layer: Executing auto correction, frame count: {FrameCount}", frameCount);
var detector = GetDetectorOrThrow();
var result = await detector.AutoCorrectionAsync(frameCount, cancellationToken);
if (!result.IsSuccess)
{
_lastError = result;
_logger?.Error(result.Exception, "自动校正失败:{Message} | Auto correction failed: {Message}", result.ErrorMessage);
}
return result;
}
catch (Exception ex)
{
var errorMsg = $"服务层自动校正异常 | Service layer auto correction exception: {ex.Message}";
_logger?.Error(ex, errorMsg);
var errorResult = DetectorResult.Failure(errorMsg, ex, -1);
_lastError = errorResult;
return errorResult;
}
}
/// <summary>
/// 应用探测器参数(Binning/PGA/帧率统一下发)| Apply detector parameters (Binning/PGA/FrameRate)
/// </summary>
public async Task<DetectorResult> ApplyParametersAsync(int binningIndex, int pga, decimal frameRate, CancellationToken cancellationToken = default)
{
try
{
_logger?.Info("服务层:应用参数,Binning={Binning}PGA={PGA},帧率={FrameRate} | Service layer: Applying parameters",
binningIndex, pga, frameRate);
var detector = GetDetectorOrThrow();
// 如果正在采集,先停止 | Stop acquisition first if running
bool wasAcquiring = detector.Status == DetectorStatus.Acquiring;
if (wasAcquiring)
{
_logger?.Info("探测器正在采集,先停止采集再应用参数 | Detector is acquiring, stopping before applying parameters");
var stopResult = await detector.StopAcquisitionAsync(cancellationToken);
if (!stopResult.IsSuccess)
{
_lastError = stopResult;
_logger?.Error(stopResult.Exception, "停止采集失败,无法应用参数:{Message} | Failed to stop acquisition, cannot apply parameters: {Message}", stopResult.ErrorMessage);
return DetectorResult.Failure($"停止采集失败,无法应用参数 | Failed to stop acquisition, cannot apply parameters: {stopResult.ErrorMessage}");
}
}
// 通过统一接口下发参数(不依赖具体探测器类型)| Apply parameters via unified interface (no dependency on specific detector type)
var result = await detector.ApplyParametersAsync(binningIndex, pga, frameRate, cancellationToken);
if (!result.IsSuccess)
{
_lastError = result;
_logger?.Error(result.Exception, "应用参数失败:{Message} | Apply parameters failed: {Message}", result.ErrorMessage);
}
else
{
_logger?.Info("参数应用成功 | Parameters applied successfully");
}
// 如果之前在采集,恢复采集 | Resume acquisition if it was running before
if (wasAcquiring)
{
_logger?.Info("参数应用完成,恢复连续采集 | Parameters applied, resuming continuous acquisition");
var startResult = await detector.StartAcquisitionAsync(cancellationToken);
if (!startResult.IsSuccess)
{
_logger?.Warn("恢复采集失败:{Message}(参数已成功应用)| Failed to resume acquisition: {Message} (parameters were applied successfully)", startResult.ErrorMessage);
}
}
return result;
}
catch (Exception ex)
{
var errorMsg = $"服务层应用参数异常 | Service layer apply parameters exception: {ex.Message}";
_logger?.Error(ex, errorMsg);
var errorResult = DetectorResult.Failure(errorMsg, ex, -1);
_lastError = errorResult;
return errorResult;
}
}
/// <summary>
/// 保存当前配置到文件 | Save current configuration to file
/// </summary>
public void SaveParameters(int binningIndex, int pga, decimal frameRate, int avgFrames)
{
try
{
_logger?.Info("保存探测器参数,Binning={Binning}PGA={PGA},帧率={FrameRate},帧合并={AvgFrames} | Saving detector parameters",
binningIndex, pga, frameRate, avgFrames);
ConfigLoader.SaveParameters(binningIndex, pga, frameRate, avgFrames);
_logger?.Info("探测器参数保存成功 | Detector parameters saved successfully");
}
catch (Exception ex)
{
_logger?.Error(ex, "保存探测器参数失败:{Message} | Failed to save detector parameters: {Message}", ex.Message);
}
}
/// <summary>
/// 获取探测器信息 | Get detector information
/// </summary>
/// <returns>探测器信息 | Detector information</returns>
public DetectorInfo GetInfo()
{
var detector = GetDetectorOrThrow();
return detector.GetInfo();
}
/// <summary>
/// 获取最后的错误信息 | Get last error information
/// </summary>
/// <returns>错误结果 | Error result</returns>
public DetectorResult GetLastError()
{
return _lastError ?? DetectorResult.Success();
}
/// <summary>
/// 获取当前探测器配置 | Get current detector configuration
/// 未初始化时尝试从配置文件加载(仅读取配置,不创建探测器实例)
/// </summary>
public DetectorConfig GetCurrentConfig()
{
if (_config != null) return _config;
// 未初始化时,尝试从配置文件加载以提供 UI 选项 | If not initialized, try loading from config for UI options
try
{
var configResult = ConfigLoader.LoadConfiguration();
if (configResult.IsSuccess)
{
_config = configResult.Data;
return _config;
}
}
catch
{
// 忽略加载异常,返回 null | Ignore load exception, return null
}
return null;
}
/// <summary>
/// 获取当前探测器的校正能力描述 | Get correction capabilities of current detector
/// 未初始化时返回基于配置文件的默认值
/// </summary>
public CorrectionCapabilities GetCorrectionCapabilities()
{
lock (_lock)
{
if (_detector != null)
{
return _detector.GetCorrectionCapabilities();
}
}
// 未初始化时从配置文件构建默认值 | Build default from config when not initialized
var config = GetCurrentConfig();
return new CorrectionCapabilities
{
DarkFrameCount = config?.DarkCorrectionFrameCount ?? 64,
GainFrameCount = config?.GainCorrectionFrameCount ?? 64
};
}
/// <summary>
/// 获取探测器实例或抛出异常 | Get detector instance or throw exception
/// </summary>
/// <returns>探测器实例 | Detector instance</returns>
/// <exception cref="InvalidOperationException">探测器未初始化 | Detector not initialized</exception>
private IAreaDetector GetDetectorOrThrow()
{
lock (_lock)
{
if (_detector == null)
{
throw new InvalidOperationException("探测器未初始化,请先调用 InitializeAsync | Detector not initialized, please call InitializeAsync first");
}
return _detector;
}
}
/// <summary>
/// 释放资源 | Dispose resources
/// </summary>
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// 释放资源 | Dispose resources
/// </summary>
/// <param name="disposing">是否释放托管资源 | Whether to dispose managed resources</param>
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
// 带超时保护的资源释放,避免退出时无限阻塞
// Dispose with timeout protection to avoid infinite blocking on exit
const int disposeTimeoutMs = 5000; // 5 秒总超时 | 5 seconds total timeout
try
{
IAreaDetector detector;
lock (_lock)
{
detector = _detector;
}
if (detector != null)
{
// 仅在正在采集时才停止采集 | Only stop acquisition if currently acquiring
if (detector.Status == DetectorStatus.Acquiring)
{
_logger?.Info("Dispose:探测器正在采集,尝试停止 | Dispose: Detector is acquiring, attempting to stop");
using var cts = new CancellationTokenSource(disposeTimeoutMs);
var stopTask = Task.Run(async () => await detector.StopAcquisitionAsync(cts.Token), cts.Token);
if (!stopTask.Wait(disposeTimeoutMs))
{
_logger?.Warn("Dispose:停止采集超时,强制继续释放 | Dispose: Stop acquisition timeout, forcing cleanup");
}
}
// 直接释放探测器资源(不再调用 DisconnectAsync 避免重复停止)
// Directly dispose detector resources (skip DisconnectAsync to avoid redundant stop)
lock (_lock)
{
_detector?.Dispose();
_detector = null;
}
_config = null;
_logger?.Info("Dispose:探测器资源已释放 | Dispose: Detector resources disposed");
}
}
catch (OperationCanceledException)
{
_logger?.Warn("Dispose:操作已取消,强制释放资源 | Dispose: Operation cancelled, forcing resource cleanup");
lock (_lock)
{
_detector?.Dispose();
_detector = null;
}
_config = null;
}
catch (AggregateException ex)
{
_logger?.Warn($"Dispose:聚合异常,强制释放资源 | Dispose: Aggregate exception, forcing cleanup: {ex.InnerException?.Message ?? ex.Message}");
lock (_lock)
{
_detector?.Dispose();
_detector = null;
}
_config = null;
}
catch (Exception ex)
{
_logger?.Error(ex, "Dispose:释放探测器资源异常 | Dispose: Exception disposing detector resources");
lock (_lock)
{
try { _detector?.Dispose(); } catch { /* 忽略 | Ignore */ }
_detector = null;
}
_config = null;
}
}
_disposed = true;
}
}
}
}