using MvCameraControl; using MvvmScaffoldFrame48.DLL.CameraTools; using MvvmScaffoldFrame48.Model.ResultModel; using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; namespace MvvmScaffoldFrame48.DLL.ThreadManager { /// /// 相机组配置和状态管理类 /// 管理单个相机的采集和处理线程及相关资源 /// public class CameraGroup { public HikCamera Camera { get; set; } public int CameraId { get; set; } public bool IsRunning { get; set; } public CancellationTokenSource CancellationTokenSource { get; set; } public Task CameraTask { get; set; } public Task ProcessingTask { get; set; } public ConcurrentQueue ImageQueue { get; set; } public SemaphoreSlim QueueSemaphore { get; set; } // 图像处理算法(接口方式) public IImageProcessingAlgorithmHikVision ImageProcessor { get; set; } // 结果发送事件,当图像处理完成时触发 public event EventHandler ProcessResultAvailable; /// /// 发送处理结果到通信线程的方法 /// 多个线程可以共用此方法 /// /// 处理结果数据 public void SendProcessResult(object resultData) { var eventArgs = new CameraProcessEventArgsResultModel { CameraId = this.CameraId, ResultData = resultData, Timestamp = DateTime.Now }; // 触发事件,通知订阅者有新的处理结果 ProcessResultAvailable?.Invoke(this, eventArgs); } /// /// 启动相机组(包括采集和处理线程) /// public void Start() { if (Camera == null) { Console.WriteLine($"相机 {CameraId} 未初始化"); return; } if(Camera.Device == null) { Console.WriteLine($"相机 {CameraId} 未初始化"); } if (Camera.Device.IsConnected == false) { Console.WriteLine($"相机 {CameraId} 未打开"); return; } if (IsRunning) return; Camera.StartReceiveFuntion(); // 重置取消令牌 CancellationTokenSource = new CancellationTokenSource(); var token = CancellationTokenSource.Token; // 启动相机采集线程 CameraTask = Task.Factory.StartNew(() => CameraCaptureLoop(token), token, TaskCreationOptions.LongRunning, TaskScheduler.Default); // 启动图像处理线程 ProcessingTask = Task.Factory.StartNew(() => ImageProcessingLoop(token), token, TaskCreationOptions.LongRunning, TaskScheduler.Default); IsRunning = true; Console.WriteLine($"相机组 {CameraId} 已启动"); } /// /// 停止相机组 /// public async void Stop() { if (!IsRunning) return; // 发送取消信号 CancellationTokenSource.Cancel(); // 等待线程完成 try { if (CameraTask != null) await CameraTask; if (ProcessingTask != null) await ProcessingTask; } catch (OperationCanceledException) { // 正常取消,忽略异常 } IsRunning = false; Camera.StopReceiveFuntion(); Console.WriteLine($"相机组 {CameraId} 已停止"); } /// /// 相机采集循环 /// private void CameraCaptureLoop(CancellationToken token) { //int frameCount = 0; try { while (!token.IsCancellationRequested) { // 模拟相机图像采集(无休眠,持续采集) if(Camera.GetOnceImage(out IFrameOut imageData)) { // 将图像放入队列 ImageQueue.Enqueue(imageData.Image.Clone() as IImage); Console.WriteLine($"相机 {CameraId} 采集到图像,帧号{imageData.FrameNum}"); QueueSemaphore.Release(); // 通知处理线程有新数据 imageData.Dispose(); } // 这里不添加休眠,保持最大帧率采集 } } catch (OperationCanceledException) { // 线程被取消,正常退出 } catch (Exception ex) { Console.WriteLine($"相机 {CameraId} 采集异常: {ex.Message}"); } } /// /// 图像处理循环 /// private async void ImageProcessingLoop(CancellationToken token) { try { while (!token.IsCancellationRequested) { // 等待图像数据 await QueueSemaphore.WaitAsync(token); // 从队列获取图像 if (ImageQueue.TryDequeue(out IImage imageData)) { // 执行图像处理逻辑 ProcessImage(imageData, CameraId); imageData.Dispose(); // 可以根据队列长度决定是否短暂休眠以避免过度占用CPU if (ImageQueue.Count == 0) { await Task.Delay(1, token); // 短暂让出CPU } } } } catch (OperationCanceledException) { // 线程被取消,正常退出 } catch (Exception ex) { Console.WriteLine($"相机 {CameraId} 处理异常: {ex.Message}"); } } /// /// 图像处理实现 /// private void ProcessImage(IImage imageData,int cameraId) { object resultData = null; try { // 优先使用接口方式的算法 if (ImageProcessor != null) { resultData = ImageProcessor.ProcessImage(imageData,cameraId); } // 如果都没有设置,则使用默认处理 else { // 默认处理逻辑 } // 发送处理结果 SendProcessResult(resultData); // 输出处理结果 //Console.WriteLine($"相机 {CameraId} 处理时间 {DateTime.Now.ToString("g")}"); } catch (Exception ex) { Console.WriteLine($"相机 {CameraId} 图像处理错误: {ex.Message}"); // 发送错误结果 //var errorResult = new ProcessResultData //{ // Result = $"Error_Camera{CameraId}_Frame{imageData.FrameNumber}_{ex.Message}", // ProcessingTime = DateTime.Now //}; //SendProcessResult(errorResult); } } } }