修改优化连接逻辑

This commit is contained in:
zqm
2025-12-31 16:34:33 +08:00
parent 526ac86414
commit f4eaee6c61
2 changed files with 167 additions and 62 deletions

View File

@@ -2818,8 +2818,8 @@ namespace JoyD.Windows.CS.Toprie
if (!_showGlobalTemperature && !_showAreaTemperature) if (!_showGlobalTemperature && !_showAreaTemperature)
return; return;
// 4. 如果勾选了全局温度,则显示全局温度(居中显示),否则显示区域温度(居中显示) // 4. 如果勾选了全局温度且未勾选区域温度,则显示全局温度(居中显示),否则显示区域温度(居中显示)
bool isGlobalTemperatureMode = _showGlobalTemperature; bool isGlobalTemperatureMode = _showGlobalTemperature && !_showAreaTemperature;
// 5. 如果勾选了区域温度,则显示区域框,否则不显示区域框 // 5. 如果勾选了区域温度,则显示区域框,否则不显示区域框
if (_showAreaTemperature) if (_showAreaTemperature)

View File

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