diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs index e408453..110a215 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs @@ -890,28 +890,18 @@ namespace JoyD.Windows.CS.Toprie return; } - // 添加额外的状态检查,避免不必要的重复启动 - if (_isReceivingTemperatureData && _temperatureReceiveThread != null && _temperatureReceiveThread.IsAlive) + // 避免重复启动 + if (_temperatureReceiveThread != null && _temperatureReceiveThread.IsAlive) { - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartTemperatureDataReceiving() - 温度数据接收已经在进行中,避免重复启动"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartTemperatureDataReceiving() - 温度数据接收线程已经在运行中,避免重复启动"); return; } - } - - Log("开始使用TCP方式接收温度数据"); - try - { - // 确保之前的连接已关闭 - StopTemperatureDataReceiving(); - // 在锁内执行所有关键状态更新,确保原子性 - lock (_lockObject) - { - // 重置停止事件 - _stopTemperatureEvent?.Dispose(); - _stopTemperatureEvent = new ManualResetEvent(false); - _isReceivingTemperatureData = true; - } - Thread.Sleep(500); + + // 重置停止事件和状态 + _stopTemperatureEvent?.Dispose(); + _stopTemperatureEvent = new ManualResetEvent(false); + // 设置接收状态为false,符合要求:系统初始化时,设置接收状态为false + _isReceivingTemperatureData = false; // 创建并启动温度数据接收线程 Thread newThread = new Thread(ReceiveTemperatureDataWithTcp) @@ -920,32 +910,29 @@ namespace JoyD.Windows.CS.Toprie Name = "TemperatureReceiveThread" }; - // 在锁内更新线程引用 - lock (_lockObject) - { - _temperatureReceiveThread = newThread; - } - + _temperatureReceiveThread = newThread; + } + + Log("开始使用TCP方式接收温度数据"); + try + { // 启动线程 - newThread.Start(); + _temperatureReceiveThread.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, "启动温度数据接收失败")); } finally { - // 确保方法执行完成时记录日志 Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartTemperatureDataReceiving() - 执行完成"); } } @@ -1149,205 +1136,185 @@ namespace JoyD.Windows.CS.Toprie { Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReceiveTemperatureDataWithTcp() - 开始执行"); - // 使用局部变量存储资源,避免在finally中访问可能已被释放的字段 + // 使用局部变量存储资源 TcpClient localTcpClient = null; NetworkStream localStream = null; List temperatureDataAccumulator = new List(); - // 根据分析,温度数据帧大小为98313字节(9字节头部+256×192×2字节数据),增大缓冲区提高接收效率 - byte[] buffer = new byte[65536]; // 增大温度数据缓冲区,减少Read操作次数 + byte[] buffer = new byte[65536]; // 缓冲区大小 try { - // 创建TCP客户端并连接到设备的温度数据端口 - localTcpClient = new TcpClient + // 主循环,持续执行直到收到停止信号 + while (true) { - ReceiveTimeout = 5000, - SendTimeout = 5000 - }; - - Log($"正在连接到温度数据端口 {TEMPERATURE_TCP_PORT}..."); - IAsyncResult result = localTcpClient.BeginConnect(_deviceIp, TEMPERATURE_TCP_PORT, null, null); - bool connected = result.AsyncWaitHandle.WaitOne(3000, true); - - if (!connected || !localTcpClient.Connected) - { - Log("温度数据TCP连接失败,超时"); - localTcpClient.Close(); - return; - } - - localTcpClient.EndConnect(result); - Log("温度数据TCP连接成功"); - - // 获取网络流 - localStream = localTcpClient.GetStream(); - localStream.ReadTimeout = 5000; - - // 更新类成员变量,在锁内进行 - lock (_lockObject) - { - _temperatureTcpClient = localTcpClient; - _temperatureStream = localStream; - // 确保接收状态为true - _isReceivingTemperatureData = true; - } - - // 发送开始温度数据传输的命令 - byte[] startCommand = Encoding.ASCII.GetBytes("start_temp_transfer\r\n"); - localStream.Write(startCommand, 0, startCommand.Length); - localStream.Flush(); - - Log("已发送开始温度数据传输命令,开始接收温度数据"); - - // 循环读取数据,使用更安全的退出机制 - bool shouldContinue = true; - while (shouldContinue) - { - // 检查停止信号和接收状态 + // 检查停止信号 bool stopRequested = false; - bool isReceiving = true; - lock (_lockObject) { if (_stopTemperatureEvent != null && _stopTemperatureEvent.WaitOne(0)) { stopRequested = true; } - isReceiving = _isReceivingTemperatureData; } if (stopRequested) { Log("接收到停止信号,准备退出温度数据接收循环"); - shouldContinue = false; break; } + // 获取当前接收状态和暂停状态 + bool isReceiving = false; + bool isPaused = false; + lock (_lockObject) + { + isReceiving = _isReceivingTemperatureData; + isPaused = _isTemperatureReceivingPaused; + } + + // 根据用户要求的逻辑处理 if (!isReceiving) { - Log("接收状态已更改(isReceiving=false),准备退出温度数据接收循环"); - shouldContinue = false; - break; - } - - try - { - // 检查连接状态 - if (localTcpClient == null || !localTcpClient.Connected) + // 如果接收状态为false + if (isPaused) { - Log("温度数据TCP连接已断开"); - shouldContinue = false; - break; + // 如果暂停,则Sleep 1秒后继续 + Log("接收状态为false且处于暂停状态,等待1秒后继续"); + Thread.Sleep(1000); + continue; } - - // 检查流是否可读 - if (localStream == null || !localStream.CanRead) + else { - Log("网络流不可读,停止接收"); - shouldContinue = false; - break; - } - - // 检查是否有数据可读,避免阻塞 - if (localStream.DataAvailable) - { - // 读取数据 - int bytesRead = localStream.Read(buffer, 0, buffer.Length); - if (bytesRead > 0) + // 否则同步创建tcp连接 + Log("接收状态为false且未暂停,创建TCP连接"); + + // 清理之前的连接 + try { - // 将读取的数据添加到累积器 - byte[] receivedBytes = new byte[bytesRead]; - Array.Copy(buffer, receivedBytes, bytesRead); + if (localStream != null) + { + localStream.Close(); + localStream = null; + } + if (localTcpClient != null) + { + localTcpClient.Close(); + localTcpClient = null; + } + } + catch (Exception ex) + { + Log($"关闭旧连接异常: {ex.Message}"); + } + + try + { + // 创建TCP客户端并连接 + localTcpClient = new TcpClient + { + ReceiveTimeout = 5000, + SendTimeout = 5000 + }; - Log($"接收到温度数据字节数: {bytesRead}"); - - // 检查是否处于暂停状态 - bool isPaused = false; - lock (_lockObject) - { - isPaused = _isTemperatureReceivingPaused; - } - + Log($"正在连接到温度数据端口 {TEMPERATURE_TCP_PORT}..."); + localTcpClient.Connect(_deviceIp, TEMPERATURE_TCP_PORT); + Log("温度数据TCP连接成功"); + + // 获取网络流 + localStream = localTcpClient.GetStream(); + localStream.ReadTimeout = 5000; + + // 更新类成员变量和状态 + lock (_lockObject) + { + _temperatureTcpClient = localTcpClient; + _temperatureStream = localStream; + _isReceivingTemperatureData = true; + } + + // 发送开始温度数据传输的命令 + byte[] startCommand = Encoding.ASCII.GetBytes("start_temp_transfer\r\n"); + localStream.Write(startCommand, 0, startCommand.Length); + localStream.Flush(); + Log("已发送开始温度数据传输命令"); + + // 更新状态标志 + isReceiving = true; + } + catch (Exception ex) + { + Log($"TCP连接或初始化失败: {ex.Message}"); + // 连接失败后等待1秒再重试 + Thread.Sleep(1000); + continue; + } + } + } + + // 如果接收状态为true + if (isReceiving && localTcpClient != null && localStream != null && localTcpClient.Connected) + { + try + { + if (localStream.DataAvailable) + { + // 读取数据 + int bytesRead = localStream.Read(buffer, 0, buffer.Length); + if (bytesRead > 0) + { + byte[] receivedBytes = new byte[bytesRead]; + Array.Copy(buffer, receivedBytes, bytesRead); + Log($"接收到温度数据字节数: {bytesRead}"); + + // 如果暂停,接收后丢弃 if (isPaused) { - Log("温度数据接收处于暂停状态,数据已接收但不处理"); - // 数据已接收但不处理,直接丢弃 + Log("接收状态为true但处于暂停状态,数据已接收但丢弃"); } else { - // 线程安全地更新累积器或直接处理 - lock (temperatureDataAccumulator) - { - temperatureDataAccumulator.AddRange(receivedBytes); - ProcessReceivedTemperatureData(temperatureDataAccumulator); - } + // 否则同步接收并处理数据 + //lock (temperatureDataAccumulator) + //{ + // temperatureDataAccumulator.AddRange(receivedBytes); + // ProcessReceivedTemperatureData(temperatureDataAccumulator); + //} } + } + else + { + // 连接已关闭 + Log("远程主机关闭了连接"); + lock (_lockObject) + { + _isReceivingTemperatureData = false; + } + continue; + } } else { - // 读取到0字节表示连接已关闭 - Log("远程主机关闭了连接"); - shouldContinue = false; - break; + // 短暂休眠避免CPU占用过高 + Thread.Sleep(10); } } - else + catch (Exception ex) { - // 如果没有数据可读,短暂休眠避免CPU占用过高 - Thread.Sleep(10); + Log($"接收数据异常: {ex.Message}"); + // 连接异常,重置状态准备重连 + lock (_lockObject) + { + _isReceivingTemperatureData = false; + } + // 短暂休眠后重试 + Thread.Sleep(100); } } - catch (TimeoutException) + else { - // 超时异常,继续尝试读取 - Log("温度数据接收超时,继续尝试"); - // 短暂休眠后重试,避免CPU占用过高 + // 没有有效连接,短暂休眠 Thread.Sleep(50); } - catch (IOException ex) - { - Log($"温度数据接收IO异常: {ex.Message}"); - // 对于网络中断异常,尝试重新连接而不是直接退出 - // 在.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) - { - Log($"温度数据接收异常: {ex.Message}"); - Log($"异常详情: {ex.StackTrace}"); - // 检查是否为严重异常 - if (ex is System.Security.SecurityException || - ex is UnauthorizedAccessException || - ex is System.Threading.ThreadAbortException) - { - Log("发生严重异常,停止温度数据接收"); - shouldContinue = false; - break; - } - else - { - Log("非致命异常,继续尝试接收温度数据"); - // 非致命异常,短暂休眠后继续尝试 - Thread.Sleep(100); - } - } } } catch (Exception ex) @@ -1362,14 +1329,11 @@ namespace JoyD.Windows.CS.Toprie lock (_lockObject) { _isReceivingTemperatureData = false; - // 不在这里调用StopTemperatureDataReceiving,避免递归调用和潜在死锁 - // 由调用者负责调用StopTemperatureDataReceiving - - // 记录线程结束信息 - Log($"温度数据接收线程已结束,重置相关状态"); + _temperatureStream = null; + _temperatureTcpClient = null; } - // 清理局部资源 + // 清理资源 try { if (localStream != null) @@ -1388,50 +1352,7 @@ namespace JoyD.Windows.CS.Toprie } 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}"); - } - } + Log("温度数据接收线程已结束,重置相关状态"); } } diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/README.md b/Windows/CS/Framework4.0/Toprie/Toprie/README.md index 9c6d3a6..719bb8b 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/README.md +++ b/Windows/CS/Framework4.0/Toprie/Toprie/README.md @@ -23,7 +23,7 @@ ### Tcp温度数据接收 1. 系统初始化时,创建后台线程。 2. 设置接收状态为false,然后线程循环执行 - 3. 如果接收状态为false,如果暂停则Sleep 1秒后继续,否则同步创建tcp连接,并同步接收和处理数据。 - 4. 如果接收状态为true,如果暂停,接收后丢弃。否则同步接收并处理数据。 - 4. Dispose时,关闭后台线程。 + 3. 如果接收状态为false,{如果暂停则Sleep 1秒后继续,否则同步创建tcp连接,并同步接收和处理数据。} + 4. 如果接收状态为true,{如果暂停,接收后丢弃。否则同步接收并处理数据。} + 5. Dispose时,关闭后台线程。 \ No newline at end of file