修复温度数据接收连接状态检查和自动重连机制
This commit is contained in:
@@ -1086,7 +1086,11 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
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[8192]; // 温度数据缓冲区
|
// 根据分析,温度数据帧大小为98313字节(9字节头部+256×192×2字节数据),增大缓冲区提高接收效率
|
||||||
|
byte[] buffer = new byte[65536]; // 增大温度数据缓冲区,减少Read操作次数
|
||||||
|
|
||||||
|
// 心跳检查时间记录,用于定期验证连接有效性
|
||||||
|
DateTime lastConnectionCheckTime = DateTime.Now;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -1181,55 +1185,111 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 检查是否有数据可读,避免阻塞
|
// 检查是否有数据可读,避免阻塞
|
||||||
if (localStream.DataAvailable)
|
if (localStream.DataAvailable)
|
||||||
|
{
|
||||||
|
// 读取数据
|
||||||
|
int bytesRead = localStream.Read(buffer, 0, buffer.Length);
|
||||||
|
if (bytesRead > 0)
|
||||||
{
|
{
|
||||||
// 读取数据
|
// 将读取的数据添加到累积器
|
||||||
int bytesRead = localStream.Read(buffer, 0, buffer.Length);
|
byte[] receivedBytes = new byte[bytesRead];
|
||||||
if (bytesRead > 0)
|
Array.Copy(buffer, receivedBytes, bytesRead);
|
||||||
{
|
|
||||||
// 将读取的数据添加到累积器
|
|
||||||
byte[] receivedBytes = new byte[bytesRead];
|
|
||||||
Array.Copy(buffer, receivedBytes, bytesRead);
|
|
||||||
|
|
||||||
Log($"接收到温度数据字节数: {bytesRead}");
|
Log($"接收到温度数据字节数: {bytesRead}");
|
||||||
|
|
||||||
// 线程安全地更新累积器或直接处理
|
// 线程安全地更新累积器或直接处理
|
||||||
lock (temperatureDataAccumulator)
|
lock (temperatureDataAccumulator)
|
||||||
{
|
|
||||||
temperatureDataAccumulator.AddRange(receivedBytes);
|
|
||||||
ProcessReceivedTemperatureData(temperatureDataAccumulator);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
// 读取到0字节表示连接已关闭
|
temperatureDataAccumulator.AddRange(receivedBytes);
|
||||||
Log("远程主机关闭了连接");
|
ProcessReceivedTemperatureData(temperatureDataAccumulator);
|
||||||
shouldContinue = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// 如果没有数据可读,短暂休眠避免CPU占用过高
|
// 读取到0字节表示连接已关闭
|
||||||
Thread.Sleep(10);
|
Log("远程主机关闭了连接");
|
||||||
|
shouldContinue = false;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// 如果没有数据可读,短暂休眠避免CPU占用过高
|
||||||
|
Thread.Sleep(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 定期检查连接状态,确保连接仍然有效
|
||||||
|
if (DateTime.Now - lastConnectionCheckTime > TimeSpan.FromSeconds(30))
|
||||||
|
{
|
||||||
|
Log("定期检查温度数据连接状态");
|
||||||
|
// 尝试发送一个简单的心跳消息到TCP连接
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (localStream != null && localStream.CanWrite)
|
||||||
|
{
|
||||||
|
byte[] heartbeat = Encoding.ASCII.GetBytes("heartbeat\r\n");
|
||||||
|
localStream.Write(heartbeat, 0, heartbeat.Length);
|
||||||
|
localStream.Flush();
|
||||||
|
Log("温度数据连接心跳发送成功");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log($"温度数据连接心跳发送失败: {ex.Message},可能需要重新连接");
|
||||||
|
}
|
||||||
|
lastConnectionCheckTime = DateTime.Now;
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (TimeoutException)
|
catch (TimeoutException)
|
||||||
{
|
{
|
||||||
// 超时异常,继续尝试读取
|
// 超时异常,继续尝试读取
|
||||||
Log("温度数据接收超时,继续尝试");
|
Log("温度数据接收超时,继续尝试");
|
||||||
|
// 短暂休眠后重试,避免CPU占用过高
|
||||||
|
Thread.Sleep(50);
|
||||||
}
|
}
|
||||||
catch (IOException ex)
|
catch (IOException ex)
|
||||||
{
|
{
|
||||||
Log($"温度数据接收IO异常: {ex.Message}");
|
Log($"温度数据接收IO异常: {ex.Message}");
|
||||||
shouldContinue = false;
|
// 对于网络中断异常,尝试重新连接而不是直接退出
|
||||||
break;
|
// 在.NET Framework 4.0中,HResult是受保护的,我们通过消息内容来判断
|
||||||
|
string exceptionMessage = ex.Message.ToLower();
|
||||||
|
if (exceptionMessage.Contains("远程主机") ||
|
||||||
|
exceptionMessage.Contains("强制关闭") ||
|
||||||
|
exceptionMessage.Contains("connection") ||
|
||||||
|
exceptionMessage.Contains("closed"))
|
||||||
|
{
|
||||||
|
Log("检测到网络连接异常,准备重新连接");
|
||||||
|
// 短暂休眠后允许循环退出,让外层逻辑处理重连
|
||||||
|
Thread.Sleep(100);
|
||||||
|
shouldContinue = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log("非致命IO异常,继续尝试接收");
|
||||||
|
// 短暂休眠后继续尝试
|
||||||
|
Thread.Sleep(50);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Log($"温度数据接收异常: {ex.Message}");
|
Log($"温度数据接收异常: {ex.Message}");
|
||||||
// 非致命异常,短暂休眠后继续尝试
|
Log($"异常详情: {ex.StackTrace}");
|
||||||
Thread.Sleep(100);
|
// 检查是否为严重异常
|
||||||
|
if (ex is System.Security.SecurityException ||
|
||||||
|
ex is UnauthorizedAccessException ||
|
||||||
|
ex is System.Threading.ThreadAbortException)
|
||||||
|
{
|
||||||
|
Log("发生严重异常,停止温度数据接收");
|
||||||
|
shouldContinue = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log("非致命异常,继续尝试接收温度数据");
|
||||||
|
// 非致命异常,短暂休眠后继续尝试
|
||||||
|
Thread.Sleep(100);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1247,6 +1307,9 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
_isReceivingTemperatureData = false;
|
_isReceivingTemperatureData = false;
|
||||||
// 不在这里调用StopTemperatureDataReceiving,避免递归调用和潜在死锁
|
// 不在这里调用StopTemperatureDataReceiving,避免递归调用和潜在死锁
|
||||||
// 由调用者负责调用StopTemperatureDataReceiving
|
// 由调用者负责调用StopTemperatureDataReceiving
|
||||||
|
|
||||||
|
// 记录线程结束信息
|
||||||
|
Log($"温度数据接收线程已结束,重置相关状态");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 清理局部资源
|
// 清理局部资源
|
||||||
@@ -1267,6 +1330,51 @@ namespace JoyD.Windows.CS.Toprie
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch {}
|
catch {}
|
||||||
|
|
||||||
|
// 重置类成员变量中的流和客户端引用
|
||||||
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
_temperatureStream = null;
|
||||||
|
_temperatureTcpClient = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 检查是否需要自动重新启动温度数据接收
|
||||||
|
// 只有当设备仍在连接状态且用户没有明确停止时才尝试重连
|
||||||
|
bool shouldAutoReconnect = false;
|
||||||
|
lock (_lockObject)
|
||||||
|
{
|
||||||
|
// 检查是否有显式的停止信号
|
||||||
|
bool hasStopSignal = _stopTemperatureEvent != null && _stopTemperatureEvent.WaitOne(0);
|
||||||
|
// 如果没有停止信号且设备应该处于连接状态,则尝试重连
|
||||||
|
shouldAutoReconnect = !hasStopSignal && _connectionStatus == ConnectionStatus.Connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldAutoReconnect)
|
||||||
|
{
|
||||||
|
Log("检测到温度数据接收线程异常退出,准备自动重连");
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// 短暂延迟后尝试重新启动温度数据接收
|
||||||
|
Thread.Sleep(2000);
|
||||||
|
// 确保在新线程中启动,避免递归调用
|
||||||
|
ThreadPool.QueueUserWorkItem(state =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Log("开始自动重新启动温度数据接收...");
|
||||||
|
StartTemperatureDataReceiving();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log($"自动重连温度数据接收失败: {ex.Message}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Log($"调度温度数据自动重连失败: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user