From ededba5906ca50958f0656a86a6f34ae489ae6f7 Mon Sep 17 00:00:00 2001 From: zqm Date: Fri, 31 Oct 2025 17:15:10 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BC=98=E5=8C=96Tcp=E6=B8=A9=E5=BA=A6?= =?UTF-8?q?=E6=95=B0=E6=8D=AE=E6=8E=A5=E6=94=B6=E7=9B=B8=E5=85=B3=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=EF=BC=8C=E4=BD=BF=E7=94=A8=E5=B1=80=E9=83=A8=E5=8F=98?= =?UTF-8?q?=E9=87=8F=E5=87=8F=E5=B0=91=E5=85=A8=E5=B1=80=E5=8F=98=E9=87=8F?= =?UTF-8?q?=E4=BE=9D=E8=B5=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Toprie/Toprie/DeviceManager.cs | 187 ++++++++++-------- 1 file changed, 100 insertions(+), 87 deletions(-) diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs index 110a215..490d454 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs @@ -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 temperatureDataAccumulator = new List(); 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 {}