diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs index ab6357c..b036661 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs @@ -198,6 +198,11 @@ namespace JoyD.Windows.CS.Toprie private string _deviceIp = "192.168.100.2"; // 设备端口 private int _devicePort = 8080; + + // 温度数据处理相关 + private volatile byte[] _lastTemperatureFrame; // 存储最后一帧温度数据 + private Thread _temperatureProcessingThread; // 温度数据处理线程 + private volatile bool _shouldStopProcessing = false; // 控制处理线程停止的标志 // 设备连接状态 private ConnectionStatus _connectionStatus = ConnectionStatus.Disconnected; // 是否已初始化 @@ -206,6 +211,8 @@ namespace JoyD.Windows.CS.Toprie private readonly bool _isDisposed = false; // 图像模式 private ImageMode _currentImageMode = ImageMode.Infrared; + // 温度数据处理锁,用于防止并发处理温度数据 + private object _temperatureProcessingLock = new object(); // 当前色彩模式 private PaletteType _currentPaletteType = PaletteType.WhiteHot; // 当前视频模式 @@ -666,6 +673,9 @@ namespace JoyD.Windows.CS.Toprie _isInitialized = true; Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Initialize() - 初始化成功,_isInitialized设为true"); + // 启动温度数据处理线程 + InitializeTemperatureProcessing(); + // 更新状态为已连接 UpdateConnectionStatus(ConnectionStatus.Connected, "SDK初始化成功"); @@ -702,6 +712,90 @@ namespace JoyD.Windows.CS.Toprie } } } + /// + /// 启动温度数据清理定时器 + /// + // 温度数据清理定时器相关方法已移除,改为直接在后台线程处理 + + /// + /// 停止温度数据清理定时器 + /// + // 温度数据清理定时器相关方法已移除,改为直接在后台线程处理 + + /// + /// 清理温度数据 + /// + /// 定时器状态对象 + /// + /// 在后台线程处理温度帧数据 + /// + /// 温度帧数据 + /// 宽度 + /// 高度 + /// + /// 初始化温度数据处理线程 + /// + private void InitializeTemperatureProcessing() + { + _shouldStopProcessing = false; + _temperatureProcessingThread = new Thread(ProcessLastTemperatureFrame); + _temperatureProcessingThread.IsBackground = true; + _temperatureProcessingThread.Name = "TemperatureProcessingThread"; + _temperatureProcessingThread.Start(); + Log("温度数据处理线程已启动"); + } + + /// + /// 处理线程方法 - 专门处理最后一帧温度数据 + /// + private void ProcessLastTemperatureFrame() + { + while (!_shouldStopProcessing) + { + try + { + // 使用Interlocked.Exchange原子操作获取并清空最后一帧数据 + byte[] frameToProcess = Interlocked.Exchange(ref _lastTemperatureFrame, null); + + // 如果有数据需要处理 + if (frameToProcess != null && !_isTemperatureReceivingPaused) + { + // 记录处理开始时间 + System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); + stopwatch.Start(); + + // 调用温度帧处理方法 + ProcessTemperatureFrame(frameToProcess, WIDTH, HEIGHT); + + // 停止计时并记录处理时间 + stopwatch.Stop(); + Log($"温度数据处理完成,耗时: {stopwatch.ElapsedMilliseconds}ms"); + } + + // 短暂睡眠避免CPU占用过高 + Thread.Sleep(50); // 可根据实际需求调整 + } + catch (Exception ex) + { + Log($"温度数据处理线程异常: {ex.Message}"); + } + } + Log("温度数据处理线程已停止"); + } + + /// + /// 停止温度数据处理线程 + /// + private void StopTemperatureProcessing() + { + _shouldStopProcessing = true; + if (_temperatureProcessingThread != null && _temperatureProcessingThread.IsAlive) + { + _temperatureProcessingThread.Join(1000); // 等待线程退出,最多等待1秒 + _temperatureProcessingThread = null; + } + } + /// /// 清理所有资源,确保安全释放 /// @@ -710,12 +804,11 @@ namespace JoyD.Windows.CS.Toprie Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CleanupResources() - 开始清理资源"); try { - // 停止所有定时器 + // 停止所有定时器和处理线程 StopAutoReconnect(); StopHeartbeat(); StopConnectionCheck(); - // 停止温度数据接收 - StopTemperatureDataReceiving(); + StopTemperatureProcessing(); // 安全释放SDK实例 A8SDK oldSdk = Interlocked.Exchange(ref _a8Sdk, null); @@ -1160,37 +1253,37 @@ namespace JoyD.Windows.CS.Toprie private void ReceiveTemperatureDataWithTcp() { Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReceiveTemperatureDataWithTcp() - 开始执行"); - + // 使用局部变量存储资源 TcpClient localTcpClient = null; NetworkStream localStream = null; List temperatureDataAccumulator = new List(); byte[] buffer = new byte[65536]; // 缓冲区大小 - + // 定义常量 const int RECEIVE_TIMEOUT = 30000; // 30秒超时 const int SLEEP_MS = 1000; // 标准等待时间 const int CONNECTION_CHECK_INTERVAL_MS = 5000; // 连接检查间隔5秒 const int LONG_SLEEP_MS = 5000; // 长等待时间 const int ERROR_SLEEP_MS = 3000; // 错误后等待时间 - + try { // 主循环,持续执行直到收到停止信号 while (!ShouldStop()) { - + // 获取当前状态和配置 bool isPaused = false; string deviceIp = null; int temperaturePort = TEMPERATURE_TCP_PORT; - + lock (_lockObject) { isPaused = _isTemperatureReceivingPaused; deviceIp = _deviceIp; } - + // 如果连接不存在或已断开,创建新连接 if (localTcpClient == null || !IsTcpClientConnected(localTcpClient)) { @@ -1200,13 +1293,13 @@ namespace JoyD.Windows.CS.Toprie Thread.Sleep(SLEEP_MS); continue; } - + // 否则创建一个新的连接实例 Log("创建新的温度数据TCP连接..."); - + // 清理之前可能存在的连接资源 CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); - + try { // 创建TCP客户端并连接 @@ -1216,24 +1309,24 @@ namespace JoyD.Windows.CS.Toprie SendTimeout = RECEIVE_TIMEOUT, ReceiveBufferSize = 65536 // 64KB }; - + Log($"正在连接到温度数据端口 {temperaturePort}..."); localTcpClient.Connect(deviceIp, temperaturePort); Log("温度数据TCP连接成功"); - + // 获取网络流 localStream = localTcpClient.GetStream(); localStream.ReadTimeout = RECEIVE_TIMEOUT; - - + + // 根据SDK文档,建立TCP连接后不需要发送任何开始命令 Log("TCP连接已建立,等待接收温度数据..."); } catch (Exception ex) { Log($"TCP连接或初始化失败: {ex.Message}"); - + // 连接失败后等待一段时间再重试 Thread.Sleep(LONG_SLEEP_MS); continue; @@ -1249,10 +1342,10 @@ namespace JoyD.Windows.CS.Toprie DateTime lastConnectionCheckTime = DateTime.Now; DateTime lastPausedLogTime = DateTime.MinValue; const int PAUSED_LOG_INTERVAL_MS = 30000; // 暂停状态日志间隔30秒 - + // 记录上次暂停状态,用于检测状态变化 bool lastPaused = false; - + // 初始化lastPaused为当前状态 lock (_lockObject) { @@ -1269,7 +1362,7 @@ namespace JoyD.Windows.CS.Toprie Log("TCP连接循环中检测到停止信号,准备退出循环"); break; } - + // 检测暂停状态是否发生变化 bool currentPaused = IsTemperatureReceivingPaused(); bool pausedChanged = currentPaused != lastPaused; @@ -1307,10 +1400,10 @@ namespace JoyD.Windows.CS.Toprie Log("暂停状态下检测到停止信号,准备退出循环"); break; } - + // 根据规范,暂停时Sleep 1秒 Thread.Sleep(1000); - + // 在暂停状态下,降低连接检查频率 if ((currentTime - lastConnectionCheckTime).TotalMilliseconds > CONNECTION_CHECK_INTERVAL_MS) { @@ -1354,7 +1447,7 @@ namespace JoyD.Windows.CS.Toprie } lastConnectionCheckTime = now; } - + if (localStream.DataAvailable) { // 有数据可读时进行阻塞读取 @@ -1380,9 +1473,9 @@ namespace JoyD.Windows.CS.Toprie // 记录处理开始时间 System.Diagnostics.Stopwatch stopwatch = new System.Diagnostics.Stopwatch(); stopwatch.Start(); - + ProcessReceivedTemperatureData(temperatureDataAccumulator); - + // 停止计时并记录处理时间 stopwatch.Stop(); Log($"处理温度数据耗时: {stopwatch.ElapsedMilliseconds}ms"); @@ -1392,9 +1485,6 @@ namespace JoyD.Windows.CS.Toprie { // 连接已关闭 Log("远程主机关闭了连接"); - - - // 清理连接资源 CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); continue; @@ -1406,12 +1496,12 @@ namespace JoyD.Windows.CS.Toprie catch (Exception ex) { Log($"接收数据异常: {ex.Message}, 堆栈: {ex.StackTrace}"); - + // 温度数据接收状态更新代码已移除,因为未被使用 - + // 清理连接资源 CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); - + // 异常后等待一段时间再重试 Thread.Sleep(ERROR_SLEEP_MS); } @@ -1421,15 +1511,15 @@ namespace JoyD.Windows.CS.Toprie finally { Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReceiveTemperatureDataWithTcp() - 执行完成"); - - // 确保状态正确更新 - // 温度数据接收状态更新代码已移除,因为未被使用 - - // 清理资源 - CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); - - Log("温度数据接收线程已结束,重置相关状态"); - } + + // 确保状态正确更新 + // 温度数据接收状态更新代码已移除,因为未被使用 + + // 清理资源 + CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); + + Log("温度数据接收线程已结束,重置相关状态"); + } } /// @@ -1619,10 +1709,10 @@ namespace JoyD.Windows.CS.Toprie // 没有剩余数据,移除当前数组 dataAccumulator.RemoveAt(0); } - - // 解析处理完整的帧数据 - //ProcessTemperatureFrame(frameData, WIDTH, HEIGHT); - + + // 只保存最后一帧数据,使用Interlocked.Exchange进行线程安全更新 + Interlocked.Exchange(ref _lastTemperatureFrame, frameData); + // 跳转到4,继续处理下一个数据 } @@ -1728,7 +1818,7 @@ namespace JoyD.Windows.CS.Toprie TemperatureData temperatureData = new TemperatureData(frameData, width, height, compensationValue); Log($"温度数据对象创建成功,分辨率: {width}x{height}"); - // 不再需要触发温度数据接收事件,移除通知机制 + LastTemperature = temperatureData; Log($"温度数据处理完成,不再触发事件通知"); } catch (Exception ex) @@ -2665,8 +2755,6 @@ namespace JoyD.Windows.CS.Toprie _isReceivingImages = false; } - // 同步停止温度数据接收 - StopTemperatureDataReceiving(); // 通知线程停止 ManualResetEvent stopEvent = null; @@ -5756,7 +5844,9 @@ namespace JoyD.Windows.CS.Toprie Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Dispose() - 开始清理资源"); try - { + { + // 同步停止温度数据接收 + StopTemperatureDataReceiving(); // 首先停止所有活动的线程和定时器 Log("[线程安全] Dispose() - 停止所有活动组件"); @@ -5765,6 +5855,7 @@ namespace JoyD.Windows.CS.Toprie try { StopConnectionCheck(); } catch (Exception ex) { Log($"停止连接检查异常: {ex.Message}"); } // 直接调用内部方法避免嵌套锁 try { StopAutoReconnectInternal(); } catch (Exception ex) { Log($"停止自动重连异常: {ex.Message}"); } + // 温度数据处理不再使用定时器,不需要停止操作 if (disposing) {