diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs index ba3085c..87dc5dc 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs @@ -2818,8 +2818,8 @@ namespace JoyD.Windows.CS.Toprie if (!_showGlobalTemperature && !_showAreaTemperature) return; - // 4. 如果勾选了全局温度,则显示全局温度(居中显示),否则显示区域温度(居中显示) - bool isGlobalTemperatureMode = _showGlobalTemperature; + // 4. 如果勾选了全局温度且未勾选区域温度,则显示全局温度(居中显示),否则显示区域温度(居中显示) + bool isGlobalTemperatureMode = _showGlobalTemperature && !_showAreaTemperature; // 5. 如果勾选了区域温度,则显示区域框,否则不显示区域框 if (_showAreaTemperature) diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs index c556f37..dead984 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs @@ -312,7 +312,16 @@ namespace JoyD.Windows.CS.Toprie /// 如果连接有效返回true,否则返回false private bool IsTcpClientConnected(TcpClient client) { - if (client == null || !client.Connected) + // 基本检查 + if (client == null) + return false; + + // 检查底层Socket是否存在 + if (client.Client == null) + return false; + + // 首先检查Connected属性 + if (!client.Connected) return false; // 检查连接状态的标准方法 @@ -321,21 +330,35 @@ namespace JoyD.Windows.CS.Toprie { // Poll方法:检查连接状态,100ms超时 // SelectMode.SelectRead:检查是否可读 + // 逻辑:如果Poll返回true,说明连接有活动 + // 如果Poll返回false且Available > 0,说明有数据可读 bool isConnected = !client.Client.Poll(100, System.Net.Sockets.SelectMode.SelectRead) || client.Client.Available > 0; - // 如果连接已断开,Client.RemoteEndPoint会抛出异常 if (isConnected) { // 尝试访问RemoteEndPoint验证连接 var dummy = client.Client.RemoteEndPoint; + + // 二次检查Connected属性,确保连接没有在检查过程中断开 + isConnected = client.Connected && client.Client.Connected; } return isConnected; } + catch (ObjectDisposedException) + { + // Socket已被释放 + return false; + } + catch (InvalidOperationException) + { + // Socket状态无效 + return false; + } catch { - // 任何异常都表示连接可能已断开 + // 任何其他异常都表示连接可能已断开 return false; } } @@ -518,6 +541,7 @@ namespace JoyD.Windows.CS.Toprie } } private TcpClient _imageTcpClient; + private TcpClient _temperatureTcpClient; // 用于跟踪当前活跃的温度数据TCP连接 // 使用CurrentImageMode代替_isInfraredMode private static readonly object _logLock = new object(); @@ -1441,7 +1465,6 @@ namespace JoyD.Windows.CS.Toprie 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]; // 缓冲区大小 @@ -1471,59 +1494,69 @@ namespace JoyD.Windows.CS.Toprie } // 如果连接不存在或已断开,创建新连接 - if (localTcpClient == null || !IsTcpClientConnected(localTcpClient)) + lock (_lockObject) { - // 如果处于暂停状态,则Sleep 1秒后继续执行 - if (isPaused) + if (_temperatureTcpClient == null || !IsTcpClientConnected(_temperatureTcpClient)) { - Thread.Sleep(SLEEP_MS); - continue; - } - - // 否则创建一个新的连接实例 - Log("创建新的温度数据TCP连接..."); - - // 清理之前可能存在的连接资源 - CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); - - try - { - // 创建TCP客户端并连接 - localTcpClient = new TcpClient + // 如果处于暂停状态,则Sleep 1秒后继续执行 + if (isPaused) { - ReceiveTimeout = RECEIVE_TIMEOUT, - SendTimeout = RECEIVE_TIMEOUT, - ReceiveBufferSize = 65536 // 64KB - }; + Thread.Sleep(SLEEP_MS); + continue; + } - Log($"正在连接到温度数据端口 {temperaturePort}..."); - localTcpClient.Connect(deviceIp, temperaturePort); - Log("温度数据TCP连接成功"); + // 否则创建一个新的连接实例 + Log("创建新的温度数据TCP连接..."); - // 获取网络流 - localStream = localTcpClient.GetStream(); - localStream.ReadTimeout = RECEIVE_TIMEOUT; + // 清理之前可能存在的连接资源 + if (_temperatureTcpClient != null) + { + try + { + _temperatureTcpClient.Close(); + _temperatureTcpClient = null; + } + catch (Exception ex) + { + Log($"关闭现有TCP连接异常: {ex.Message}"); + } + } + try + { + // 创建TCP客户端并连接 + _temperatureTcpClient = new TcpClient + { + ReceiveTimeout = RECEIVE_TIMEOUT, + SendTimeout = RECEIVE_TIMEOUT, + ReceiveBufferSize = 65536 // 64KB + }; - - // 根据SDK文档,建立TCP连接后不需要发送任何开始命令 - Log("TCP连接已建立,等待接收温度数据..."); - } - catch (Exception ex) - { - Log($"TCP连接或初始化失败: {ex.Message}"); - - // 连接失败后等待一段时间再重试 - Thread.Sleep(LONG_SLEEP_MS); - continue; + Log($"正在连接到温度数据端口 {temperaturePort}..."); + _temperatureTcpClient.Connect(deviceIp, temperaturePort); + Log("温度数据TCP连接成功"); + } + catch (Exception ex) + { + Log($"TCP连接或初始化失败: {ex.Message}"); + _temperatureTcpClient = null; + // 连接失败后等待一段时间再重试 + Thread.Sleep(LONG_SLEEP_MS); + continue; + } } } // 数据接收处理:使用已建立的连接持续接收数据 - if (localTcpClient != null && localTcpClient.Connected && localStream != null) + if (_temperatureTcpClient != null && _temperatureTcpClient.Connected) { try { + // 获取网络流 + localStream = _temperatureTcpClient.GetStream(); + localStream.ReadTimeout = RECEIVE_TIMEOUT; + Log("TCP连接已建立,等待接收温度数据..."); + // 记录连接检查时间 DateTime lastConnectionCheckTime = DateTime.Now; DateTime lastPausedLogTime = DateTime.MinValue; @@ -1540,7 +1573,7 @@ namespace JoyD.Windows.CS.Toprie } // 持续读取温度数据流 - while (localTcpClient != null && localTcpClient.Connected) + while (_temperatureTcpClient != null && _temperatureTcpClient.Connected) { // 每次循环开始时检查是否收到停止信号 if (ShouldStop()) @@ -1593,10 +1626,14 @@ namespace JoyD.Windows.CS.Toprie // 在暂停状态下,降低连接检查频率 if ((currentTime - lastConnectionCheckTime).TotalMilliseconds > CONNECTION_CHECK_INTERVAL_MS) { - if (localTcpClient != null && !IsTcpClientConnected(localTcpClient)) + lock (_lockObject) { - Log("暂停状态下检测到连接已断开,将在恢复时重建连接"); - CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); + if (_temperatureTcpClient != null && !IsTcpClientConnected(_temperatureTcpClient)) + { + Log("暂停状态下检测到连接已断开,将在恢复时重建连接"); + _temperatureTcpClient.Close(); + _temperatureTcpClient = null; + } } lastConnectionCheckTime = currentTime; } @@ -1605,12 +1642,16 @@ namespace JoyD.Windows.CS.Toprie else { // 只有从暂停状态恢复时(状态从true变为false的瞬间),才检查和重建连接 - if (pausedChanged && localTcpClient != null && !IsTcpClientConnected(localTcpClient)) + lock (_lockObject) { - Log("恢复接收时检测到连接无效,需要重建连接"); - CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); - // 跳出内层循环,回到外层循环重新建立连接 - break; + if (pausedChanged && _temperatureTcpClient != null && !IsTcpClientConnected(_temperatureTcpClient)) + { + Log("恢复接收时检测到连接无效,需要重建连接"); + _temperatureTcpClient.Close(); + _temperatureTcpClient = null; + // 跳出内层循环,回到外层循环重新建立连接 + break; + } } // 根据SDK文档,建立TCP连接后不需要发送任何开始命令 // 从暂停状态恢复时,只需继续监听数据流即可 @@ -1625,11 +1666,16 @@ namespace JoyD.Windows.CS.Toprie DateTime now = DateTime.Now; if ((now - lastConnectionCheckTime).TotalMilliseconds > CONNECTION_CHECK_INTERVAL_MS) { - if (localTcpClient != null && !IsTcpClientConnected(localTcpClient)) + lock (_lockObject) { - Log("检测到连接已断开,准备重建连接"); - CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); - continue; + if (_temperatureTcpClient != null && !IsTcpClientConnected(_temperatureTcpClient)) + { + Log("检测到连接已断开,准备重建连接"); + _temperatureTcpClient.Close(); + _temperatureTcpClient = null; + // 跳出内层循环,回到外层循环重新建立连接 + break; + } } lastConnectionCheckTime = now; } @@ -1672,8 +1718,15 @@ namespace JoyD.Windows.CS.Toprie // 连接已关闭 Log("远程主机关闭了连接"); // 清理连接资源 - CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); - continue; + lock (_lockObject) + { + if (_temperatureTcpClient != null) + { + _temperatureTcpClient.Close(); + _temperatureTcpClient = null; + } + } + break; } } } @@ -1686,11 +1739,34 @@ namespace JoyD.Windows.CS.Toprie // 温度数据接收状态更新代码已移除,因为未被使用 // 清理连接资源 - CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); + lock (_lockObject) + { + if (_temperatureTcpClient != null) + { + _temperatureTcpClient.Close(); + _temperatureTcpClient = null; + } + } // 异常后等待一段时间再重试 Thread.Sleep(ERROR_SLEEP_MS); } + finally + { + // 关闭网络流 + if (localStream != null) + { + try + { + localStream.Close(); + localStream = null; + } + catch (Exception ex) + { + Log($"关闭网络流异常: {ex.Message}"); + } + } + } } } } @@ -1702,7 +1778,36 @@ namespace JoyD.Windows.CS.Toprie // 温度数据接收状态更新代码已移除,因为未被使用 // 清理资源 - CleanupConnectionResources(localStream, localTcpClient, out localStream, out localTcpClient); + // 关闭网络流 + if (localStream != null) + { + try + { + localStream.Close(); + localStream = null; + } + catch (Exception ex) + { + Log($"关闭网络流异常: {ex.Message}"); + } + } + + // 关闭TCP客户端 + lock (_lockObject) + { + if (_temperatureTcpClient != null) + { + try + { + _temperatureTcpClient.Close(); + _temperatureTcpClient = null; + } + catch (Exception ex) + { + Log($"关闭TCP客户端异常: {ex.Message}"); + } + } + } Log("温度数据接收线程已结束,重置相关状态"); }