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