更新DeviceManager.cs文件

This commit is contained in:
zqm
2025-11-04 16:46:40 +08:00
parent 264e5f458d
commit cadf6f3c89

View File

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