优化Tcp温度数据接收相关代码,使用局部变量减少全局变量依赖

This commit is contained in:
zqm
2025-10-31 17:15:10 +08:00
parent eeb4615b27
commit ededba5906

View File

@@ -867,6 +867,10 @@ namespace JoyD.Windows.CS.Toprie
{ {
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartTemperatureDataReceiving() - 开始执行"); Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartTemperatureDataReceiving() - 开始执行");
// 局部变量用于跟踪线程状态
Thread newThread = null;
bool canProceed = false;
// 在设计模式下,跳过实际的温度数据接收 // 在设计模式下,跳过实际的温度数据接收
if (IsDesignMode) if (IsDesignMode)
{ {
@@ -902,22 +906,28 @@ namespace JoyD.Windows.CS.Toprie
_stopTemperatureEvent = new ManualResetEvent(false); _stopTemperatureEvent = new ManualResetEvent(false);
// 设置接收状态为false符合要求系统初始化时设置接收状态为false // 设置接收状态为false符合要求系统初始化时设置接收状态为false
_isReceivingTemperatureData = false; _isReceivingTemperatureData = false;
_isTemperatureReceivingPaused = false; // 确保暂停状态也重置
// 创建并启动温度数据接收线程 // 创建并启动温度数据接收线程
Thread newThread = new Thread(ReceiveTemperatureDataWithTcp) newThread = new Thread(ReceiveTemperatureDataWithTcp)
{ {
IsBackground = true, IsBackground = true,
Name = "TemperatureReceiveThread" Name = "TemperatureReceiveThread"
}; };
// 更新全局线程引用
_temperatureReceiveThread = newThread; _temperatureReceiveThread = newThread;
canProceed = true;
} }
// 仅在可以继续的情况下启动线程
if (canProceed && newThread != null)
{
Log("开始使用TCP方式接收温度数据"); Log("开始使用TCP方式接收温度数据");
try try
{ {
// 启动线程 // 启动线程
_temperatureReceiveThread.Start(); newThread.Start();
} }
catch (Exception ex) catch (Exception ex)
{ {
@@ -931,8 +941,8 @@ namespace JoyD.Windows.CS.Toprie
OnConnectionException(new ConnectionExceptionEventArgs(ex, "启动温度数据接收失败")); OnConnectionException(new ConnectionExceptionEventArgs(ex, "启动温度数据接收失败"));
} }
finally }
{
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartTemperatureDataReceiving() - 执行完成"); Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartTemperatureDataReceiving() - 执行完成");
} }
} }
@@ -1009,17 +1019,25 @@ namespace JoyD.Windows.CS.Toprie
{ {
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopTemperatureDataReceiving() - 开始执行"); Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopTemperatureDataReceiving() - 开始执行");
if (_isDisposed) // 使用局部变量检查对象是否已释放
bool objectDisposed = false;
lock (_lockObject)
{
objectDisposed = _isDisposed;
}
if (objectDisposed)
{ {
Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopTemperatureDataReceiving() - 对象已释放,跳过操作"); Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopTemperatureDataReceiving() - 对象已释放,跳过操作");
return; return;
} }
// 使用变量保存需要释放的资源,减少锁的持有时间 // 使用局部变量保存需要释放的资源,减少锁的持有时间
ManualResetEvent stopEventToDispose = null; ManualResetEvent stopEventToDispose = null;
Thread threadToJoin = null; Thread threadToJoin = null;
NetworkStream streamToClose = null;
TcpClient clientToClose = null; // 定义常量
const int THREAD_JOIN_TIMEOUT_MS = 2000;
try try
{ {
@@ -1030,14 +1048,11 @@ namespace JoyD.Windows.CS.Toprie
_isTemperatureReceivingPaused = false; // 同时重置暂停状态 _isTemperatureReceivingPaused = false; // 同时重置暂停状态
stopEventToDispose = _stopTemperatureEvent; stopEventToDispose = _stopTemperatureEvent;
threadToJoin = _temperatureReceiveThread; threadToJoin = _temperatureReceiveThread;
streamToClose = _temperatureStream;
clientToClose = _temperatureTcpClient;
// 立即重置引用,避免资源被重新使用 // 立即重置引用,避免资源被重新使用
_temperatureStream = null;
_temperatureTcpClient = null;
_temperatureReceiveThread = null; _temperatureReceiveThread = null;
_stopTemperatureEvent = null; _stopTemperatureEvent = null;
// 注意不再重置_temperatureStream和_temperatureTcpClient因为它们已在接收线程中作为局部变量处理
} }
// 在锁外通知线程停止,避免死锁 // 在锁外通知线程停止,避免死锁
@@ -1058,7 +1073,7 @@ namespace JoyD.Windows.CS.Toprie
{ {
Log("等待温度接收线程结束..."); Log("等待温度接收线程结束...");
// 增加等待时间,确保线程有足够时间完成清理 // 增加等待时间,确保线程有足够时间完成清理
if (threadToJoin.Join(2000)) // 等待最多2秒 if (threadToJoin.Join(THREAD_JOIN_TIMEOUT_MS)) // 等待最多2秒
{ {
Log("温度接收线程已正常停止"); Log("温度接收线程已正常停止");
} }
@@ -1068,31 +1083,6 @@ namespace JoyD.Windows.CS.Toprie
} }
} }
// 在锁外关闭TCP客户端和流避免死锁
if (streamToClose != null)
{
try
{
streamToClose.Close();
}
catch (Exception ex)
{
Log($"关闭NetworkStream时出现异常: {ex.Message}");
}
}
if (clientToClose != null)
{
try
{
clientToClose.Close();
}
catch (Exception ex)
{
Log($"关闭TcpClient时出现异常: {ex.Message}");
}
}
// 释放停止事件 // 释放停止事件
if (stopEventToDispose != null) if (stopEventToDispose != null)
{ {
@@ -1116,8 +1106,6 @@ namespace JoyD.Windows.CS.Toprie
lock (_lockObject) lock (_lockObject)
{ {
_isReceivingTemperatureData = false; _isReceivingTemperatureData = false;
_temperatureStream = null;
_temperatureTcpClient = null;
_temperatureReceiveThread = null; _temperatureReceiveThread = null;
} }
} }
@@ -1136,40 +1124,49 @@ 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; 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 = 5000;
const int SHORT_SLEEP_MS = 10;
const int MEDIUM_SLEEP_MS = 50;
const int LONG_SLEEP_MS = 1000;
const int ERROR_SLEEP_MS = 100;
try try
{ {
// 主循环,持续执行直到收到停止信号 // 主循环,持续执行直到收到停止信号
while (true) while (true)
{ {
// 检查停止信号 // 检查停止信号和对象是否已释放
bool stopRequested = false; bool shouldStop = false;
lock (_lockObject) lock (_lockObject)
{ {
if (_stopTemperatureEvent != null && _stopTemperatureEvent.WaitOne(0)) shouldStop = (_stopTemperatureEvent != null && _stopTemperatureEvent.WaitOne(0)) || _isDisposed;
{
stopRequested = true;
}
} }
if (stopRequested) if (shouldStop)
{ {
Log("接收到停止信号,准备退出温度数据接收循环"); Log("接收到停止信号或对象已释放,准备退出温度数据接收循环");
break; break;
} }
// 获取当前接收状态暂停状态 // 获取当前接收状态暂停状态和设备IP
bool isReceiving = false; bool isReceiving = false;
bool isPaused = false; bool isPaused = false;
string deviceIp = null;
int temperaturePort = 0;
lock (_lockObject) lock (_lockObject)
{ {
isReceiving = _isReceivingTemperatureData; isReceiving = _isReceivingTemperatureData;
isPaused = _isTemperatureReceivingPaused; isPaused = _isTemperatureReceivingPaused;
deviceIp = _deviceIp;
temperaturePort = TEMPERATURE_TCP_PORT;
} }
// 根据用户要求的逻辑处理 // 根据用户要求的逻辑处理
@@ -1180,7 +1177,7 @@ namespace JoyD.Windows.CS.Toprie
{ {
// 如果暂停则Sleep 1秒后继续 // 如果暂停则Sleep 1秒后继续
Log("接收状态为false且处于暂停状态等待1秒后继续"); Log("接收状态为false且处于暂停状态等待1秒后继续");
Thread.Sleep(1000); Thread.Sleep(LONG_SLEEP_MS);
continue; continue;
} }
else else
@@ -1212,23 +1209,21 @@ namespace JoyD.Windows.CS.Toprie
// 创建TCP客户端并连接 // 创建TCP客户端并连接
localTcpClient = new TcpClient localTcpClient = new TcpClient
{ {
ReceiveTimeout = 5000, ReceiveTimeout = RECEIVE_TIMEOUT,
SendTimeout = 5000 SendTimeout = RECEIVE_TIMEOUT
}; };
Log($"正在连接到温度数据端口 {TEMPERATURE_TCP_PORT}..."); Log($"正在连接到温度数据端口 {temperaturePort}...");
localTcpClient.Connect(_deviceIp, TEMPERATURE_TCP_PORT); localTcpClient.Connect(deviceIp, temperaturePort);
Log("温度数据TCP连接成功"); Log("温度数据TCP连接成功");
// 获取网络流 // 获取网络流
localStream = localTcpClient.GetStream(); localStream = localTcpClient.GetStream();
localStream.ReadTimeout = 5000; localStream.ReadTimeout = RECEIVE_TIMEOUT;
// 更新类成员变量和状态 // 更新必要的状态标志
lock (_lockObject) lock (_lockObject)
{ {
_temperatureTcpClient = localTcpClient;
_temperatureStream = localStream;
_isReceivingTemperatureData = true; _isReceivingTemperatureData = true;
} }
@@ -1238,14 +1233,14 @@ namespace JoyD.Windows.CS.Toprie
localStream.Flush(); localStream.Flush();
Log("已发送开始温度数据传输命令"); Log("已发送开始温度数据传输命令");
// 更新状态标志 // 更新局部状态标志
isReceiving = true; isReceiving = true;
} }
catch (Exception ex) catch (Exception ex)
{ {
Log($"TCP连接或初始化失败: {ex.Message}"); Log($"TCP连接或初始化失败: {ex.Message}");
// 连接失败后等待1秒再重试 // 连接失败后等待1秒再重试
Thread.Sleep(1000); Thread.Sleep(LONG_SLEEP_MS);
continue; continue;
} }
} }
@@ -1274,11 +1269,11 @@ namespace JoyD.Windows.CS.Toprie
else else
{ {
// 否则同步接收并处理数据 // 否则同步接收并处理数据
//lock (temperatureDataAccumulator) lock (temperatureDataAccumulator)
//{ {
// temperatureDataAccumulator.AddRange(receivedBytes); temperatureDataAccumulator.AddRange(receivedBytes);
// ProcessReceivedTemperatureData(temperatureDataAccumulator); ProcessReceivedTemperatureData(temperatureDataAccumulator);
//} }
} }
} }
else else
@@ -1289,13 +1284,22 @@ namespace JoyD.Windows.CS.Toprie
{ {
_isReceivingTemperatureData = false; _isReceivingTemperatureData = false;
} }
// 清理连接资源
try
{
localStream.Close();
localTcpClient.Close();
}
catch {}
localStream = null;
localTcpClient = null;
continue; continue;
} }
} }
else else
{ {
// 短暂休眠避免CPU占用过高 // 短暂休眠避免CPU占用过高
Thread.Sleep(10); Thread.Sleep(SHORT_SLEEP_MS);
} }
} }
catch (Exception ex) catch (Exception ex)
@@ -1306,14 +1310,23 @@ namespace JoyD.Windows.CS.Toprie
{ {
_isReceivingTemperatureData = false; _isReceivingTemperatureData = false;
} }
// 清理连接资源
try
{
localStream.Close();
localTcpClient.Close();
}
catch {}
localStream = null;
localTcpClient = null;
// 短暂休眠后重试 // 短暂休眠后重试
Thread.Sleep(100); Thread.Sleep(ERROR_SLEEP_MS);
} }
} }
else else
{ {
// 没有有效连接,短暂休眠 // 没有有效连接,短暂休眠
Thread.Sleep(50); Thread.Sleep(MEDIUM_SLEEP_MS);
} }
} }
} }
@@ -1329,8 +1342,6 @@ namespace JoyD.Windows.CS.Toprie
lock (_lockObject) lock (_lockObject)
{ {
_isReceivingTemperatureData = false; _isReceivingTemperatureData = false;
_temperatureStream = null;
_temperatureTcpClient = null;
} }
// 清理资源 // 清理资源
@@ -1339,6 +1350,7 @@ namespace JoyD.Windows.CS.Toprie
if (localStream != null) if (localStream != null)
{ {
localStream.Close(); localStream.Close();
localStream = null;
} }
} }
catch {} catch {}
@@ -1348,6 +1360,7 @@ namespace JoyD.Windows.CS.Toprie
if (localTcpClient != null) if (localTcpClient != null)
{ {
localTcpClient.Close(); localTcpClient.Close();
localTcpClient = null;
} }
} }
catch {} catch {}