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);
}
}
}
}