From eb96e4f15188a2c618898408147013563f26909f Mon Sep 17 00:00:00 2001 From: zqm Date: Tue, 28 Oct 2025 13:08:56 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E8=BF=9E?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CS/Framework4.0/Toprie/Toprie/Camera.cs | 169 +- .../Toprie/Toprie/DeviceManager.cs | 1483 +++++++++++++---- .../Toprie/Toprie/UdpCommunicationManager.cs | 134 +- Windows/CS/Framework4.0/Toprie/Toprie/V8.cs | 67 +- 4 files changed, 1469 insertions(+), 384 deletions(-) diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs index 3eea4bc..a58df52 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/Camera.cs @@ -35,7 +35,7 @@ namespace JoyD.Windows.CS.Toprie // 清空现有日志 try { - string logFile = Path.Combine(Application.StartupPath, "camera.log"); + string logFile = Path.Combine(Application.StartupPath, "log.txt"); if (File.Exists(logFile)) { File.WriteAllText(logFile, string.Empty); @@ -570,28 +570,74 @@ namespace JoyD.Windows.CS.Toprie /// 设备管理器连接状态变更事件处理 /// private void DeviceManager_ConnectionStatusChanged(object sender, ConnectionStatusChangedEventArgs e) - { - // 确保在UI线程上更新,并且检查控件是否已被释放 - if (!this.IsDisposed && !this.Disposing) - { + { + // 参数验证 + if (e == null) + { + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 警告: 接收到空的连接状态变更事件参数"); + return; + } + + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] 接收连接状态变更事件: {e.Status}"); + + // 捕获所有可能的异常,确保事件处理器不会崩溃 + try + { + // 首先检查控件状态 + if (this.IsDisposed || this.Disposing) + { + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 控件已释放或正在释放,跳过UI更新"); + return; + } + + // 检查事件参数中的状态信息 + string statusMessage = $"连接状态变更为: {e.Status}"; + if (!string.IsNullOrEmpty(e.DeviceInfo)) + { + statusMessage += $" (设备信息: {e.DeviceInfo})"; + } + + // 线程安全处理 - 确保在UI线程上更新 if (this.InvokeRequired) - { + { try - { + { // 使用BeginInvoke代替Invoke,避免可能的死锁问题 - this.BeginInvoke(new Action(() => HandleConnectionStatusChanged(e))); + this.BeginInvoke(new Action(args => + { + // 再次检查控件状态,防止在异步调用期间控件被释放 + if (!this.IsDisposed && !this.Disposing) + { + HandleConnectionStatusChanged(args); + } + else + { + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 异步调用期间控件已释放,跳过处理"); + } + }), e); } - catch (ObjectDisposedException) - { + catch (ObjectDisposedException ode) + { // 捕获控件已释放异常,避免程序崩溃 - Console.WriteLine("控件已释放,跳过UI更新"); + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 控件已释放,无法进行UI线程调用: {ode.Message}"); + } + catch (InvalidOperationException ioe) + { + // 捕获无效操作异常,通常发生在控件状态异常时 + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] UI线程调用无效: {ioe.Message}"); } } else - { + { + // 直接在UI线程上处理 HandleConnectionStatusChanged(e); } } + catch (Exception ex) + { + // 捕获所有其他异常,记录并继续 + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 处理连接状态变更事件异常: {ex.Message}\n{ex.StackTrace}"); + } } /// @@ -738,37 +784,94 @@ namespace JoyD.Windows.CS.Toprie /// 设备管理器连接异常事件处理 /// private void DeviceManager_ConnectionException(object sender, ConnectionExceptionEventArgs e) - { - // 确保在UI线程上更新,并且检查控件是否已被释放 - if (!this.IsDisposed && !this.Disposing) - { + { + // 参数验证 + if (e == null) + { + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 警告: 接收到空的连接异常事件参数"); + return; + } + + // 记录详细的异常信息,但避免在UI线程上执行耗时操作 + string exceptionMessage = e.Exception != null ? e.Exception.Message : "无详细异常信息"; + string stackTrace = e.Exception != null ? e.Exception.StackTrace : "无堆栈信息"; + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] 接收连接异常事件: {e.Message}\n{exceptionMessage}\n{stackTrace}"); + + // 捕获所有可能的异常,确保异常处理不会导致程序崩溃 + try + { + // 首先检查控件状态 + if (this.IsDisposed || this.Disposing) + { + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 控件已释放或正在释放,跳过异常显示"); + return; + } + + // 创建用于UI显示的错误消息 + string uiErrorMessage = $"连接异常: {e.Message}"; + if (string.IsNullOrEmpty(e.Message) && e.Exception != null) + { + uiErrorMessage = $"连接异常: {exceptionMessage}"; + } + + // 线程安全处理 - 确保在UI线程上更新 if (this.InvokeRequired) - { + { try - { - // 使用BeginInvoke在UI线程上显示错误 - this.BeginInvoke(new Action(() => - { - // 记录异常日志 - Console.WriteLine($"连接异常发生于 {DateTime.Now}: {e.Message}\n{e.Exception.Message}\n{e.Exception.StackTrace}"); - - ShowError($"连接异常: {e.Message}"); + { + // 创建局部变量保存错误消息,避免闭包问题 + string errorMsg = uiErrorMessage; + + // 使用BeginInvoke代替Invoke,避免可能的死锁问题 + this.BeginInvoke(new Action(() => + { + // 再次检查控件状态,防止在异步调用期间控件被释放 + if (!this.IsDisposed && !this.Disposing) + { + try + { + ShowError(errorMsg); + } + catch (Exception showEx) + { + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 显示错误消息异常: {showEx.Message}"); + } + } + else + { + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 异步调用期间控件已释放,跳过错误显示"); + } })); } - catch (ObjectDisposedException) - { + catch (ObjectDisposedException ode) + { // 捕获控件已释放异常,避免程序崩溃 - Console.WriteLine("控件已释放,跳过异常处理"); + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 控件已释放,无法进行UI线程调用: {ode.Message}"); + } + catch (InvalidOperationException ioe) + { + // 捕获无效操作异常,通常发生在控件状态异常时 + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] UI线程调用无效: {ioe.Message}"); } } else - { - // 记录异常日志 - Console.WriteLine($"连接异常发生于 {DateTime.Now}: {e.Message}\n{e.Exception.Message}\n{e.Exception.StackTrace}"); - - ShowError($"连接异常: {e.Message}"); + { + // 直接在UI线程上处理 + try + { + ShowError(uiErrorMessage); + } + catch (Exception showEx) + { + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 显示错误消息异常: {showEx.Message}"); + } } } + catch (Exception ex) + { + // 捕获所有其他异常,记录并继续 + Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 处理连接异常事件异常: {ex.Message}\n{ex.StackTrace}"); + } } /// diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs index 3d356ba..08852cb 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/DeviceManager.cs @@ -182,6 +182,10 @@ namespace JoyD.Windows.CS.Toprie private const int ConnectionCheckInterval = 5000; // 心跳间隔(毫秒) private int _heartbeatInterval = 5000; + // 最后接收数据时间戳 + private DateTime _lastDataReceivedTime = DateTime.MinValue; + // 数据接收超时时间(毫秒) + private const int DataReceivedTimeout = 15000; // 15秒内未收到数据则认为连接可能断开 // TCP客户端 // 该变量已在文件上方定义,删除重复实现 // 网络流 @@ -233,7 +237,7 @@ namespace JoyD.Windows.CS.Toprie } catch (Exception ex) { - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 捕获异常: {ex.Message}"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] IsNetworkAvailable() - 捕获异常: {ex.Message}"); return false; } } @@ -300,66 +304,169 @@ namespace JoyD.Windows.CS.Toprie /// 相关异常(如果有) private void UpdateConnectionStatus(ConnectionStatus newStatus, string message = null, Exception exception = null) { - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 尝试更新状态: {_connectionStatus} -> {newStatus}, 消息: {message}"); - // 检查对象是否已被释放 - if (_isDisposed) + // 使用线程安全的方式记录方法进入 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 开始执行"); + + lock (_lockObject) // 添加线程同步锁 { - Log("警告: 尝试在已释放对象上更新连接状态"); - return; + // 检查对象是否已被释放 + if (_isDisposed) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 对象已释放,忽略状态更新"); + return; + } + + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 尝试更新状态: {_connectionStatus} -> {newStatus}, 消息: {message}"); + + bool statusChanged = (_connectionStatus != newStatus); + ConnectionStatus oldStatus = _connectionStatus; + + if (statusChanged) + { + _connectionStatus = newStatus; + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 状态已更新: {oldStatus} -> {newStatus}"); + + // 触发连接状态变更事件前再次检查对象是否已被释放 + if (!_isDisposed) + { + try + { + OnConnectionStatusChanged(new ConnectionStatusChangedEventArgs(newStatus, message)); + } + catch (Exception ex) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 触发连接状态变更事件异常: {ex.Message}"); + } + } + + Log($"连接状态变更: {oldStatus} -> {newStatus}"); + if (!string.IsNullOrEmpty(message)) + { + Log($"状态消息: {message}"); + } + if (exception != null) + { + Log($"异常信息: {exception.Message}"); + } + + // 保存状态变更相关信息供后续处理 + ConnectionStatus finalNewStatus = newStatus; + bool shouldReconnect = (newStatus == ConnectionStatus.Disconnected && _autoReconnectEnabled && oldStatus != ConnectionStatus.Connecting); + bool shouldReset = (newStatus == ConnectionStatus.Connected); + + // 添加状态转换验证,避免不合理的状态切换 + bool isValidTransition = ValidateStatusTransition(oldStatus, newStatus); + if (!isValidTransition) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 无效的状态转换: {oldStatus} -> {newStatus},已忽略"); + return; + } + + // 添加额外的保护:防止短时间内状态频繁变化导致的闪烁问题 + // 1. 当从Connected转换到Reconnecting时,检查是否真的需要重连 + if (oldStatus == ConnectionStatus.Connected && newStatus == ConnectionStatus.Reconnecting) + { + // 检查当前是否有其他重连操作正在进行 + if (Interlocked.CompareExchange(ref _isReconnecting, 1, 1) == 1) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 检测到重连操作正在进行,推迟状态转换: {oldStatus} -> {newStatus}"); + return; + } + } + + // 2. 当从Reconnecting快速切换回Connected时,确保消息不会引起混淆 + if (oldStatus == ConnectionStatus.Reconnecting && newStatus == ConnectionStatus.Connected && message.Contains("正在进行自动重连")) + { + // 修改消息内容,使其更准确 + message = "重连成功,设备已恢复连接"; + } + + // 在锁外执行可能耗时的操作 + ThreadPool.QueueUserWorkItem((state) => + { + try + { + if (shouldReconnect) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 在锁外启动自动重连"); + StartAutoReconnect(); + } + else if (shouldReset) + { + lock (_lockObject) // 重置时需要加锁 + { + if (!_isDisposed) + { + _currentReconnectAttempt = 0; + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 连接成功,已重置重连计数"); + } + } + } + } + catch (Exception ex) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 后续操作异常: {ex.Message}"); + } + }); + } + else + { + // 优化:只有在调试模式且有异常时才记录调用堆栈,减少日志量 + if (System.Diagnostics.Debugger.IsAttached || exception != null || (!string.IsNullOrEmpty(message) && !message.Contains("正在进行自动重连"))) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 状态未变化({_connectionStatus}),消息: {message}"); + + // 仅在调试模式且有异常时才记录调用堆栈,避免频繁的堆栈记录 + #if DEBUG + if (exception != null) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 调用堆栈: {Environment.StackTrace}"); + } + #endif + } + } } - if (_connectionStatus != newStatus) - { - ConnectionStatus oldStatus = _connectionStatus; - _connectionStatus = newStatus; - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 状态已更新: {oldStatus} -> {newStatus}"); - - // 触发连接状态变更事件前再次检查对象是否已被释放 - if (!_isDisposed) - { - try - { - OnConnectionStatusChanged(new ConnectionStatusChangedEventArgs(newStatus, message)); - } - catch (Exception ex) - { - Log($"触发连接状态变更事件异常: {ex.Message}"); - } - } - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 异常处理完成"); - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 连接检查正常完成"); - - Log($"连接状态变更: {oldStatus} -> {newStatus}"); - if (!string.IsNullOrEmpty(message)) - { - Log($"状态消息: {message}"); - } - if (exception != null) - { - Log($"异常信息: {exception.Message}"); - } - - // 如果断开连接且启用了自动重连,启动重连机制 - if (newStatus == ConnectionStatus.Disconnected && _autoReconnectEnabled && oldStatus != ConnectionStatus.Connecting) - { - StartAutoReconnect(); - } - // 如果连接成功,重置重连计数并启动图像接收 - else if (newStatus == ConnectionStatus.Connected) - { - _currentReconnectAttempt = 0; - StopAutoReconnect(); - // 启动图像接收 - StartImageReceiving(); - } - // 如果断开连接,停止图像接收 - else if (newStatus == ConnectionStatus.Disconnected) - { - StopImageReceiving(); - } - } + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] UpdateConnectionStatus() - 执行完成"); } + /// + /// 验证状态转换的有效性 + /// + /// 当前状态 + /// 目标状态 + /// 是否为有效的状态转换 + private bool ValidateStatusTransition(ConnectionStatus fromStatus, ConnectionStatus toStatus) + { + // 如果状态相同,认为是有效的(但会在主方法中跳过实际变更) + if (fromStatus == toStatus) + return true; + + // 定义有效的状态转换规则 + switch (fromStatus) + { + case ConnectionStatus.Disconnected: + // 断开状态可以转换为连接中或重连中 + return toStatus == ConnectionStatus.Connecting || toStatus == ConnectionStatus.Reconnecting; + + case ConnectionStatus.Connecting: + // 连接中状态可以转换为已连接或断开 + return toStatus == ConnectionStatus.Connected || toStatus == ConnectionStatus.Disconnected; + + case ConnectionStatus.Connected: + // 已连接状态可以转换为断开或重连中 + // 允许直接从Connected转换到Reconnecting,以支持更灵活的重连机制 + return toStatus == ConnectionStatus.Disconnected || toStatus == ConnectionStatus.Reconnecting; + + case ConnectionStatus.Reconnecting: + // 重连中状态可以转换为已连接或断开 + return toStatus == ConnectionStatus.Connected || toStatus == ConnectionStatus.Disconnected; + + default: + return false; + } + } + /// /// 初始化设备管理器 /// @@ -384,8 +491,18 @@ namespace JoyD.Windows.CS.Toprie return true; } - try + // 加锁进行线程安全的初始化 + lock (_lockObject) { + // 再次检查,因为可能在获取锁的过程中已被其他线程初始化 + if (_isInitialized) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Initialize() - 已被其他线程初始化,直接返回成功"); + return true; + } + + try + { // 清理旧资源(如果有) Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Initialize() - 清理旧资源"); CleanupResources(); @@ -407,6 +524,9 @@ namespace JoyD.Windows.CS.Toprie return false; } + // 更新状态为连接中 + UpdateConnectionStatus(ConnectionStatus.Connecting, "正在初始化设备连接"); + // 首先调用SDK静态初始化方法 - 这是连接成功的关键步骤! // 添加重试机制,增强初始化可靠性 int initResult = -1; @@ -451,15 +571,37 @@ namespace JoyD.Windows.CS.Toprie _isInitialized = true; Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Initialize() - 初始化成功,_isInitialized设为true"); + + // 更新状态为已连接 + UpdateConnectionStatus(ConnectionStatus.Connected, "SDK初始化成功"); + + // 连接成功后,停止自动重连(如果正在运行) + StopAutoReconnect(); + + // 启动图像接收 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Initialize() - 连接成功,启动图像接收"); + StartImageReceiving(); + return true; } catch (Exception ex) { Log($"SDK初始化失败: {ex.Message},堆栈: {ex.StackTrace}"); _isInitialized = false; - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Initialize() - 初始化异常,_isInitialized保持false: {ex.Message}"); - OnConnectionException(new ConnectionExceptionEventArgs(ex, "初始化设备管理器失败")); - return false; + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Initialize() - 初始化异常,_isInitialized保持false: {ex.Message}"); + OnConnectionException(new ConnectionExceptionEventArgs(ex, "初始化设备管理器失败")); + // 更新状态为断开 + UpdateConnectionStatus(ConnectionStatus.Disconnected, "初始化失败", ex); + return false; + } + finally + { + // 确保在异常情况下也能清理资源 + if (!_isInitialized && _connectionStatus == ConnectionStatus.Connecting) + { + UpdateConnectionStatus(ConnectionStatus.Disconnected, "初始化未完成"); + } + } } } @@ -582,6 +724,8 @@ namespace JoyD.Windows.CS.Toprie break; } } + // 添加心跳检测异常处理,但位置应该在CheckConnectionValidity方法中 + // 这里保持PingDevice方法的纯净性 if (isInSameSubnet) { @@ -654,8 +798,43 @@ namespace JoyD.Windows.CS.Toprie /// /// 事件参数 protected virtual void OnConnectionStatusChanged(ConnectionStatusChangedEventArgs e) - { - ConnectionStatusChanged?.Invoke(this, e); + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnConnectionStatusChanged() - 开始执行,状态: {e.Status}"); + + // 检查参数有效性 + if (e == null) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnConnectionStatusChanged() - 参数为空,跳过事件触发"); + return; + } + + // 获取事件处理程序的快照,避免在多线程环境中出现竞态条件 + EventHandler handler = ConnectionStatusChanged; + + // 检查是否有订阅者 + if (handler != null) + { + // 获取所有订阅的委托,单独处理每个处理器 + Delegate[] invocationList = handler.GetInvocationList(); + + foreach (Delegate d in invocationList) + { + try + { + // 安全地转换并调用每个处理器 + EventHandler invoker = (EventHandler)d; + invoker(this, e); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnConnectionStatusChanged() - 成功触发一个事件处理器: {d.Method.Name}"); + } + catch (Exception ex) + { + // 捕获单个事件处理器的异常,确保其他处理器仍能被调用 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnConnectionStatusChanged() - 事件处理器异常: {ex.Message},堆栈: {ex.StackTrace}"); + } + } + } + + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnConnectionStatusChanged() - 执行完成"); } /// @@ -663,39 +842,105 @@ namespace JoyD.Windows.CS.Toprie /// private void StartConnectionCheck() { - try + lock (_lockObject) // 添加线程同步锁 { - // 首先停止现有的连接检查,确保资源释放 - StopConnectionCheck(); - - Console.WriteLine("启动连接状态检查,每5秒检查一次"); - - // 使用try-catch包装定时器创建,避免异常 try { - // 每5秒检查一次连接状态 - _connectionCheckTimer = new System.Threading.Timer(state => + // 首先停止现有的连接检查,确保资源释放 + StopConnectionCheck(); + + Log("启动连接状态检查,每5秒检查一次"); // 统一使用Log方法 + + // 使用try-catch包装定时器创建,避免异常 + try { - // 确保定时器状态检查在工作线程中安全执行 - try + // 使用非重复模式的定时器,避免前一个检查未完成就开始新的检查 + _connectionCheckTimer = new System.Threading.Timer(state => { - // 避免在定时器回调中可能的资源访问冲突 - if (_connectionCheckTimer == null) - return; - - // 关键修改:即使_isInitialized为false,也需要检查连接状态 - // 当显示为已连接但初始化状态为false时,必须检查连接 - if (_connectionStatus == ConnectionStatus.Connected) + // 确保定时器状态检查在工作线程中安全执行 + try { - // 如果初始化失败但显示已连接,尝试重新初始化 - if (!_isInitialized) + // 避免在定时器回调中可能的资源访问冲突 + if (_connectionCheckTimer == null) + return; + + lock (_lockObject) // 添加线程同步锁保护状态访问 { - Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] 警告: 显示已连接但初始化状态为false,尝试重新初始化..."); - Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] 当前状态: _connectionStatus={_connectionStatus}, _isInitialized={_isInitialized}, _a8Sdk={(_a8Sdk == null ? "null" : "已初始化")}, _currentDeviceId={_currentDeviceId}"); - if (!Initialize()) + if (_isDisposed) + return; + + // 关键修改:即使_isInitialized为false,也需要检查连接状态 + // 当显示为已连接但初始化状态为false时,必须检查连接 + if (_connectionStatus == ConnectionStatus.Connected) { - Console.WriteLine("重新初始化失败,确认连接已断开"); - UpdateConnectionStatus(ConnectionStatus.Disconnected, "设备未初始化,连接已断开"); + // 如果初始化失败但显示已连接,尝试重新初始化 + if (!_isInitialized) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] 警告: 显示已连接但初始化状态为false,尝试重新初始化..."); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] 当前状态: _connectionStatus={_connectionStatus}, _isInitialized={_isInitialized}, _a8Sdk={(_a8Sdk == null ? "null" : "已初始化")}, _currentDeviceId={_currentDeviceId}"); + + // 避免在定时器回调中直接调用可能阻塞的方法 + // 使用线程池执行初始化 + ThreadPool.QueueUserWorkItem((obj) => + { + lock (_lockObject) + { + if (!_isDisposed && _connectionStatus == ConnectionStatus.Connected && !_isInitialized) + { + if (!Initialize()) + { + Log("重新初始化失败,确认连接已断开"); + UpdateConnectionStatus(ConnectionStatus.Disconnected, "设备未初始化,连接已断开"); + // 启动自动重连 + if (_autoReconnectEnabled) + { + StartAutoReconnect(); + } + } + } + } + }); + } + + // 无论初始化状态如何,只要显示为已连接就进行检查 + // 复制状态变量到局部变量以避免在检查过程中状态被修改 + bool isConnected = _connectionStatus == ConnectionStatus.Connected; + bool isInitialized = _isInitialized; + A8SDK sdkInstance = _a8Sdk; + int deviceId = _currentDeviceId; + + // 在锁外执行检查以避免阻塞 + ThreadPool.QueueUserWorkItem((obj) => + { + CheckConnectionWrapper(); + }); + } + // 正常情况下的连接检查 + else if (_isInitialized && _a8Sdk != null && _currentDeviceId != -1) + { + // 复制状态变量到局部变量以避免在检查过程中状态被修改 + bool isInitialized = _isInitialized; + A8SDK sdkInstance = _a8Sdk; + int deviceId = _currentDeviceId; + + // 在锁外执行检查以避免阻塞 + ThreadPool.QueueUserWorkItem((obj) => + { + CheckConnectionWrapper(); + }); + } + } + } + catch (Exception ex) + { + Log($"定时器回调异常: {ex.Message}"); + // 异常时如果是已连接状态,将其设为断开 + lock (_lockObject) + { + if (!_isDisposed && _connectionStatus == ConnectionStatus.Connected) + { + UpdateConnectionStatus(ConnectionStatus.Disconnected, "连接检查异常", ex); + _isInitialized = false; // 启动自动重连 if (_autoReconnectEnabled) { @@ -703,98 +948,125 @@ namespace JoyD.Windows.CS.Toprie } } } - - // 无论初始化状态如何,只要显示为已连接就进行检查 - CheckConnectionWrapper(); + // 发生异常时停止定时器,避免持续报错 + StopConnectionCheck(); } - // 正常情况下的连接检查 - else if (_isInitialized && _a8Sdk != null && _currentDeviceId != -1) + finally { - CheckConnectionWrapper(); - } - } - catch (Exception ex) - { - Log($"定时器回调异常: {ex.Message}"); - // 异常时如果是已连接状态,将其设为断开 - if (_connectionStatus == ConnectionStatus.Connected) - { - UpdateConnectionStatus(ConnectionStatus.Disconnected, "连接检查异常", ex); - _isInitialized = false; - // 启动自动重连 - if (_autoReconnectEnabled) + // 检查完成后,如果定时器仍存在且未释放,重新启动定时器 + // 这样可以确保一个检查完成后才开始下一个检查 + lock (_lockObject) { - StartAutoReconnect(); + if (!_isDisposed && _connectionCheckTimer != null) + { + try + { + _connectionCheckTimer.Change(5000, Timeout.Infinite); + } + catch (ObjectDisposedException) + { + // 忽略已释放对象的异常 + } + } } } - // 发生异常时停止定时器,避免持续报错 - StopConnectionCheck(); - } - }, null, 5000, 5000); + }, null, 5000, Timeout.Infinite); + } + catch (Exception ex) + { + Log($"创建连接检查定时器失败: {ex.Message}"); + _connectionCheckTimer = null; + } } catch (Exception ex) { - Log($"创建连接检查定时器失败: {ex.Message}"); - _connectionCheckTimer = null; + Log($"启动连接检查异常: {ex.Message}"); + StopConnectionCheck(); } } - catch (Exception ex) - { - Log($"启动连接检查异常: {ex.Message}"); - StopConnectionCheck(); - } } // 连接检查的安全包装方法 private void CheckConnectionWrapper() { Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 开始连接检查"); + + // 先检查对象状态,避免不必要的操作 + lock (_lockObject) + { + if (_isDisposed || _connectionStatus != ConnectionStatus.Connected) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 对象已释放或连接状态非Connected,跳过检查"); + return; + } + } + + // 在锁外执行连接有效性检查,避免长时间阻塞 + bool isStillConnected; try { - // 检查连接有效性 - bool isStillConnected = CheckConnectionValidity(); + isStillConnected = CheckConnectionValidity(); Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - CheckConnectionValidity返回: {isStillConnected}"); - - // 连接状态变化时更新状态 - if (!isStillConnected && _connectionStatus == ConnectionStatus.Connected) - { - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 检测到连接已断开: _connectionStatus={_connectionStatus}, isStillConnected={isStillConnected}, _isInitialized={_isInitialized}"); - // 断开连接时重置初始化状态和SDK实例 - _isInitialized = false; - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 重置初始化状态为false"); - _a8Sdk = null; - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 释放SDK实例"); - UpdateConnectionStatus(ConnectionStatus.Disconnected, "连接已断开:设备离线"); - // 断开连接后自动启动重连 - if (_autoReconnectEnabled) - { - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 连接断开,启动自动重连"); - StartAutoReconnect(); - } - } - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 连接检查正常完成"); } catch (Exception ex) { Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 检查连接状态异常: {ex.Message}"); - // 检查异常时,将状态设为断开 - if (_connectionStatus == ConnectionStatus.Connected) + isStillConnected = false; + } + + // 如果连接无效,需要在锁内更新状态 + if (!isStillConnected) + { + lock (_lockObject) { - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 异常时连接状态为Connected,需要重置"); - // 异常时重置初始化状态和SDK实例 - _isInitialized = false; - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 异常时重置初始化状态为false"); - _a8Sdk = null; - UpdateConnectionStatus(ConnectionStatus.Disconnected, "连接状态检查异常", ex); - // 异常时启动自动重连 - if (_autoReconnectEnabled) + if (!_isDisposed && _connectionStatus == ConnectionStatus.Connected) { - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 检查异常,启动自动重连"); - StartAutoReconnect(); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 检测到连接已断开: _connectionStatus={_connectionStatus}, isStillConnected={isStillConnected}, _isInitialized={_isInitialized}"); + // 断开连接时重置初始化状态和SDK实例 + _isInitialized = false; + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 重置初始化状态为false"); + + // 安全释放SDK实例 + A8SDK oldSdk = _a8Sdk; + _a8Sdk = null; + + // 在锁外释放资源 + if (oldSdk != null) + { + ThreadPool.QueueUserWorkItem((obj) => + { + try + { + // 注意:A8SDK类没有Dispose方法,这里只记录日志 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - SDK实例引用已处理"); + } + catch (Exception disposeEx) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] SDK资源释放异常: {disposeEx.Message}"); + } + }); + } + else + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - SDK实例已为空,无需释放"); + } + + UpdateConnectionStatus(ConnectionStatus.Disconnected, "连接已断开:设备离线"); + + // 断开连接后自动启动重连,但在锁外执行 + if (_autoReconnectEnabled) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 连接断开,将启动自动重连"); + // 在锁外启动自动重连,避免潜在的死锁 + ThreadPool.QueueUserWorkItem((obj) => + { + StartAutoReconnect(); + }); + } } } - Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 异常处理完成"); } + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionWrapper() - 连接检查完成"); } /// @@ -810,6 +1082,9 @@ namespace JoyD.Windows.CS.Toprie return true; } + // 注意:此方法被CheckConnectionWrapper调用,已经在线程安全的上下文中 + // 不需要额外加锁,但需要确保SDK实例的访问是线程安全的 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionValidity() - 开始检查连接有效性"); try { @@ -847,7 +1122,9 @@ namespace JoyD.Windows.CS.Toprie if (_a8Sdk == null) { Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionValidity() - SDK实例不存在,重新初始化..."); - _a8Sdk = new A8SDK(_deviceIp); + // 先创建新实例,再原子赋值,避免中间状态 + A8SDK newSdk = new A8SDK(_deviceIp); + _a8Sdk = newSdk; Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] CheckConnectionValidity() - SDK实例已创建"); } @@ -1005,8 +1282,43 @@ namespace JoyD.Windows.CS.Toprie /// /// 事件参数 protected virtual void OnConnectionException(ConnectionExceptionEventArgs e) - { - ConnectionException?.Invoke(this, e); + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnConnectionException() - 开始执行"); + + // 检查参数有效性 + if (e == null) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnConnectionException() - 参数为空,跳过事件触发"); + return; + } + + // 获取事件处理程序的快照,避免在多线程环境中出现竞态条件 + EventHandler handler = ConnectionException; + + // 检查是否有订阅者 + if (handler != null) + { + // 获取所有订阅的委托,单独处理每个处理器 + Delegate[] invocationList = handler.GetInvocationList(); + + foreach (Delegate d in invocationList) + { + try + { + // 安全地转换并调用每个处理器 + EventHandler invoker = (EventHandler)d; + invoker(this, e); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnConnectionException() - 成功触发一个事件处理器: {d.Method.Name}"); + } + catch (Exception ex) + { + // 捕获单个事件处理器的异常,确保其他处理器仍能被调用 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnConnectionException() - 事件处理器异常: {ex.Message},堆栈: {ex.StackTrace}"); + } + } + } + + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnConnectionException() - 执行完成"); } /// @@ -1014,8 +1326,56 @@ namespace JoyD.Windows.CS.Toprie /// /// 事件参数 protected virtual void OnImageReceived(ImageReceivedEventArgs e) - { - ImageReceived?.Invoke(this, e); + { + // 图像事件可能高频触发,只记录重要日志以避免性能影响 + bool isDebugMode = false; // 可配置是否启用详细日志 + + if (isDebugMode) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnImageReceived() - 开始执行"); + } + + // 检查参数有效性 + if (e == null) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnImageReceived() - 警告: 参数为空,跳过事件触发"); + return; + } + + // 获取事件处理程序的快照,避免在多线程环境中出现竞态条件 + EventHandler handler = ImageReceived; + + // 检查是否有订阅者 + if (handler != null) + { + // 获取所有订阅的委托,单独处理每个处理器 + Delegate[] invocationList = handler.GetInvocationList(); + + foreach (Delegate d in invocationList) + { + try + { + // 安全地转换并调用每个处理器 + EventHandler invoker = (EventHandler)d; + invoker(this, e); + + if (isDebugMode) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnImageReceived() - 成功触发处理器: {d.Method.Name}"); + } + } + catch (Exception ex) + { + // 捕获单个事件处理器的异常,确保其他处理器仍能被调用 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnImageReceived() - 处理器异常: {ex.Message},堆栈: {ex.StackTrace}"); + } + } + } + + if (isDebugMode) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] OnImageReceived() - 执行完成"); + } } #region 公共属性 @@ -1177,14 +1537,34 @@ namespace JoyD.Windows.CS.Toprie /// public void StartImageReceiving() { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartImageReceiving() - 开始执行"); + // 在设计模式下,跳过实际的图像接收 if (IsDesignMode) { Log("设计模式下跳过实际的图像接收"); return; } + + lock (_lockObject) + { + // 检查对象是否已被释放 + if (_isDisposed) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartImageReceiving() - 对象已释放,忽略操作"); + return; + } + + // 检查连接状态 + if (_connectionStatus != ConnectionStatus.Connected) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartImageReceiving() - 连接未建立,无法开始图像接收"); + return; + } + } - Console.WriteLine("开始使用HTTP方式接收图像数据"); + Log("开始使用HTTP方式接收图像数据"); + bool existed = false; try { // 确保之前的连接已关闭 @@ -1192,7 +1572,10 @@ namespace JoyD.Windows.CS.Toprie // 重置停止事件 _stopImageEvent = new ManualResetEvent(false); - _isReceivingImages = true; + lock (_lockObject) + { + _isReceivingImages = true; + } // 创建并启动图像接收线程 _imageReceiveThread = new Thread(ReceiveImageDataWithHttpWebRequest) @@ -1205,8 +1588,19 @@ namespace JoyD.Windows.CS.Toprie catch (Exception ex) { // 记录异常 - Console.WriteLine("StartImageReceiving error: " + ex.Message); - _isReceivingImages = false; + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartImageReceiving() - 异常: {ex.Message}"); + lock (_lockObject) + { + _isReceivingImages = false; + } + + // 如果连接状态异常,触发异常事件 + OnConnectionException(new ConnectionExceptionEventArgs(ex, "启动图像接收失败")); + } + finally + { + // 确保方法执行完成时记录日志 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartImageReceiving() - 执行完成"); } } @@ -1215,47 +1609,140 @@ namespace JoyD.Windows.CS.Toprie /// public void StopImageReceiving() { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopImageReceiving() - 开始执行"); + + if (_isDisposed) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopImageReceiving() - 对象已释放,跳过操作"); + return; + } + try { - _isReceivingImages = false; + // 线程安全地更新状态 + lock (_lockObject) + { + _isReceivingImages = false; + } // 通知线程停止 - if (_stopImageEvent != null) + ManualResetEvent stopEvent = null; + lock (_lockObject) { - _stopImageEvent.Set(); + stopEvent = _stopImageEvent; + } + + if (stopEvent != null) + { + try + { + stopEvent.Set(); + } + catch (ObjectDisposedException) + { + // 忽略已释放的事件 + } } // 等待线程结束 - if (_imageReceiveThread != null && _imageReceiveThread.IsAlive) + Thread imageThread = null; + lock (_lockObject) { - _imageReceiveThread.Join(3000); // 最多等待3秒 - _imageReceiveThread = null; + imageThread = _imageReceiveThread; + } + + if (imageThread != null && imageThread.IsAlive) + { + try + { + imageThread.Join(3000); // 最多等待3秒 + lock (_lockObject) + { + if (_imageReceiveThread == imageThread) // 确保没有被其他线程修改 + { + _imageReceiveThread = null; + } + } + } + catch (ThreadStateException) + { + // 忽略线程状态异常 + } } // 停止重连线程 - if (_imageReconnectThread != null && _imageReconnectThread.IsAlive) + Thread reconnectThread = null; + lock (_lockObject) { - _imageReconnectThread.Join(1000); - _imageReconnectThread = null; + reconnectThread = _imageReconnectThread; + } + + if (reconnectThread != null && reconnectThread.IsAlive) + { + try + { + reconnectThread.Join(1000); + lock (_lockObject) + { + if (_imageReconnectThread == reconnectThread) // 确保没有被其他线程修改 + { + _imageReconnectThread = null; + } + } + } + catch (ThreadStateException) + { + // 忽略线程状态异常 + } } // 释放资源 - if (_imageStream != null) + Stream stream = null; + lock (_lockObject) { - _imageStream.Close(); - _imageStream.Dispose(); + stream = _imageStream; _imageStream = null; } - - if (_imageTcpClient != null) + + if (stream != null) { - _imageTcpClient.Close(); + try + { + stream.Close(); + stream.Dispose(); + } + catch (Exception) + { + // 忽略释放资源时的异常 + } + } + + TcpClient tcpClient = null; + lock (_lockObject) + { + tcpClient = _imageTcpClient; _imageTcpClient = null; } + + if (tcpClient != null) + { + try + { + tcpClient.Close(); + } + catch (Exception) + { + // 忽略关闭连接时的异常 + } + } } catch (Exception ex) { - Console.WriteLine("StopImageReceiving error: " + ex.Message); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopImageReceiving() - 异常: {ex.Message}"); + } + finally + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopImageReceiving() - 执行完成"); } } @@ -1347,6 +1834,9 @@ namespace JoyD.Windows.CS.Toprie { if (data == null || data.Length == 0) return; + + // 更新最后接收数据时间戳 + _lastDataReceivedTime = DateTime.Now; // 检查是否为HTTP响应 if (IsHttpResponse(data)) @@ -1731,7 +2221,8 @@ namespace JoyD.Windows.CS.Toprie /// 设置色彩模式 /// /// 色彩模式 - public void SetPaletteType(PaletteType paletteType) + /// 设置是否成功 + public bool SetPaletteType(PaletteType paletteType) { try { @@ -1742,14 +2233,29 @@ namespace JoyD.Windows.CS.Toprie int paletteValue = (int)paletteType; // 尝试设置色彩模式 + int originalValue = _a8Sdk.Color_plate; // 先获取当前值 _a8Sdk.Color_plate = paletteValue; - Console.WriteLine($"色彩模式设置成功: {paletteType} (值: {paletteValue})"); + + // 验证设置是否成功(通过再次读取确认) + int currentValue = _a8Sdk.Color_plate; + if (currentValue == paletteValue) + { + Console.WriteLine($"色彩模式设置成功: {paletteType} (值: {paletteValue})"); + return true; + } + else + { + Console.WriteLine($"色彩模式设置失败: 未能确认设置生效,当前值: {currentValue}"); + return false; + } } + Console.WriteLine("色彩模式设置失败: SDK实例为空"); + return false; } catch (Exception ex) { Console.WriteLine($"设置色彩模式失败: {ex.Message}"); - // 发生异常时可以考虑恢复到之前的设置或记录错误 + return false; } } @@ -2483,12 +2989,120 @@ namespace JoyD.Windows.CS.Toprie private volatile bool _isConnecting = false; private void StartAutoReconnect() - { - // 停止现有的重连定时器 - StopAutoReconnect(); + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 开始执行"); - // 创建新的重连定时器 - 使用一次性定时器而非重复定时器 - _reconnectTimer = new System.Threading.Timer(ReconnectCallback, null, 0, Timeout.Infinite); + // 检查对象是否已释放 + if (_isDisposed) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 对象已释放,取消重连"); + return; + } + + // 如果已经在连接状态,不需要启动重连 + if (_connectionStatus == ConnectionStatus.Connected) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 设备已连接,无需启动重连"); + return; + } + + try + { + // 使用锁确保线程安全,避免创建多个重连定时器 + lock (_lockObject) + { + // 再次检查状态,防止在获取锁期间状态已变更 + if (_isDisposed || _connectionStatus == ConnectionStatus.Connected) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 状态已变更,取消重连启动"); + return; + } + + // 停止现有的重连定时器 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 停止现有重连定时器"); + StopAutoReconnectInternal(); // 使用内部方法避免重复获取锁 + + // 使用Interlocked.Exchange安全创建新的重连定时器 + System.Threading.Timer newTimer = new System.Threading.Timer( + ReconnectCallback, + null, + 1000, // 延迟1秒后启动,避免过于频繁 + Timeout.Infinite); + + // 确保原子性地替换定时器引用 + System.Threading.Timer oldTimer = Interlocked.Exchange(ref _reconnectTimer, newTimer); + + // 如果有旧定时器没有被StopAutoReconnectInternal释放,确保这里也释放它 + if (oldTimer != null && oldTimer != newTimer) + { + try + { + oldTimer.Change(Timeout.Infinite, Timeout.Infinite); + oldTimer.Dispose(); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 释放了未被清理的旧定时器"); + } + catch (Exception ex) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 清理旧定时器时发生异常: {ex.Message}"); + } + } + + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 成功创建并启动重连定时器"); + } + } + catch (Exception ex) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 创建重连定时器失败: {ex.Message},堆栈: {ex.StackTrace}"); + + // 触发连接异常事件 + try + { + if (!_isDisposed) + { + OnConnectionException(new ConnectionExceptionEventArgs(ex, "启动自动重连失败")); + } + } + catch (Exception ex2) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 触发异常事件失败: {ex2.Message}"); + } + } + + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartAutoReconnect() - 执行完成"); + } + + /// + /// 内部停止重连方法,不获取锁,用于已在锁内的调用 + /// + private void StopAutoReconnectInternal() + { + try + { + System.Threading.Timer timerToStop = Interlocked.Exchange(ref _reconnectTimer, null); + if (timerToStop != null) + { + try + { + timerToStop.Change(Timeout.Infinite, Timeout.Infinite); + timerToStop.Dispose(); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopAutoReconnectInternal() - 重连定时器已停止并释放"); + } + catch (ObjectDisposedException) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopAutoReconnectInternal() - 重连定时器已被释放"); + } + } + + // 重置重连尝试次数 + Interlocked.Exchange(ref _currentReconnectAttempt, 0); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopAutoReconnectInternal() - 重连尝试次数已重置"); + } + catch (Exception ex) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopAutoReconnectInternal() - 异常: {ex.Message}"); + // 确保即使异常,引用也被清空 + Interlocked.Exchange(ref _reconnectTimer, null); + } } /// @@ -2533,28 +3147,33 @@ namespace JoyD.Windows.CS.Toprie /// 停止自动重连 /// private void StopAutoReconnect() - { + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopAutoReconnect() - 开始执行"); + + if (_isDisposed) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopAutoReconnect() - 对象已释放,跳过操作"); + return; + } + try - { - // 使用局部变量暂存,避免多线程访问时的空引用问题 - System.Threading.Timer timerToDispose = Interlocked.Exchange(ref _reconnectTimer, null); - if (timerToDispose != null) - { - // 立即停止定时器,避免回调执行 - timerToDispose.Change(Timeout.Infinite, Timeout.Infinite); - // 安全释放定时器资源 - timerToDispose.Dispose(); - Console.WriteLine("自动重连已停止"); + { + // 使用锁确保线程安全 + lock (_lockObject) + { + // 调用内部方法执行实际停止操作 + StopAutoReconnectInternal(); } - - // 重置重连尝试次数 - _currentReconnectAttempt = 0; } catch (Exception ex) - { - Console.WriteLine($"停止自动重连异常: {ex.Message}"); + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopAutoReconnect() - 异常: {ex.Message}"); // 确保即使异常,引用也被清空 - _reconnectTimer = null; + Interlocked.Exchange(ref _reconnectTimer, null); + } + finally + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopAutoReconnect() - 执行完成"); } } @@ -2564,41 +3183,61 @@ namespace JoyD.Windows.CS.Toprie /// 定时器状态 private void ReconnectCallback(object state) { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 开始执行"); + // 使用Interlocked.Exchange实现原子操作检查,防止重入 if (Interlocked.Exchange(ref _isReconnecting, 1) != 0) { - Console.WriteLine("检测到重连回调正在执行,避免重入"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 检测到重连回调正在执行,避免重入"); return; } try { - // 检查是否已达到最大重连次数 - if (_currentReconnectAttempt >= _maxReconnectAttempts) + if (_isDisposed) { - Console.WriteLine($"已达到最大重连次数 ({_maxReconnectAttempts}),停止自动重连"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 对象已释放,跳过重连"); + return; + } + + // 检查是否已达到最大重连次数 + int currentAttempts = Interlocked.CompareExchange(ref _currentReconnectAttempt, 0, 0); + if (currentAttempts >= _maxReconnectAttempts) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 已达到最大重连次数 ({_maxReconnectAttempts}),停止自动重连"); StopAutoReconnect(); UpdateConnectionStatus(ConnectionStatus.Disconnected, "已达到最大重连次数,请手动检查设备状态"); return; } // 改进的重连间隔递增策略,避免指数增长过快 - int currentInterval = Math.Min(_reconnectInterval * (int)(1 + _currentReconnectAttempt * 0.5), 30000); // 最多30秒 + int currentInterval = Math.Min(_reconnectInterval * (int)(1 + currentAttempts * 0.5), 30000); // 最多30秒 - _currentReconnectAttempt++; - Console.WriteLine($"自动重连尝试 {_currentReconnectAttempt}/{_maxReconnectAttempts},当前间隔: {currentInterval}ms"); + // 线程安全地递增重连尝试次数 + Interlocked.Increment(ref _currentReconnectAttempt); + currentAttempts++; + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 自动重连尝试 {currentAttempts}/{_maxReconnectAttempts},当前间隔: {currentInterval}ms"); // 在重试前先检查网络状态 if (!IsNetworkAvailable()) { - Console.WriteLine("网络不可用,推迟重连尝试"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 网络不可用,推迟重连尝试"); UpdateConnectionStatus(ConnectionStatus.Disconnected, "网络连接不可用,请检查网络设置"); // 网络不可用时,调整为重试间隔较长 int networkDownInterval = Math.Min(_reconnectInterval * 3, 15000); - if (_reconnectTimer != null) + // 安全地更新定时器 + System.Threading.Timer timerToUpdate = _reconnectTimer; + if (timerToUpdate != null) { - _reconnectTimer.Change(networkDownInterval, Timeout.Infinite); + try + { + timerToUpdate.Change(networkDownInterval, Timeout.Infinite); + } + catch (ObjectDisposedException) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 定时器已被释放,无法更新网络不可用状态的重连间隔"); + } } return; } @@ -2609,13 +3248,19 @@ namespace JoyD.Windows.CS.Toprie bool connectionSuccessful = false; // 仅用IP地址重连设备,这样更直接更快 - if (!string.IsNullOrEmpty(_deviceIp)) + string deviceIp = null; + lock (_lockObject) { - Console.WriteLine($"用IP地址 {_deviceIp} 重连设备"); + deviceIp = _deviceIp; + } + + if (!string.IsNullOrEmpty(deviceIp)) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 用IP地址 {deviceIp} 重连设备"); try { // 检查IP是否可达,使用改进的PingDevice方法 - if (PingDevice(_deviceIp)) + if (PingDevice(deviceIp)) { // 使用Interlocked.Exchange确保线程安全地释放旧实例 A8SDK oldSdk = Interlocked.Exchange(ref _a8Sdk, null); @@ -2623,18 +3268,18 @@ namespace JoyD.Windows.CS.Toprie { try { - Console.WriteLine("安全释放旧SDK实例资源"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 安全释放旧SDK实例资源"); // 注意:根据SDK文档,如果有destroy方法应调用 } catch (Exception ex) { - Console.WriteLine($"释放旧SDK实例资源时发生异常: {ex.Message}"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 释放旧SDK实例资源时发生异常: {ex.Message}"); } } // 创建新的SDK实例 - Console.WriteLine($"创建新的SDK实例,目标IP: {_deviceIp}"); - A8SDK newSdk = new A8SDK(_deviceIp); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 创建新的SDK实例,目标IP: {deviceIp}"); + A8SDK newSdk = new A8SDK(deviceIp); // 保存到字段前进行验证,避免无效实例 bool isConnected = false; @@ -2644,13 +3289,13 @@ namespace JoyD.Windows.CS.Toprie { try { - Console.WriteLine($"尝试建立连接并发送心跳包...(尝试 {retry + 1}/{maxHeartbeatRetries})"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 尝试建立连接并发送心跳包...(尝试 {retry + 1}/{maxHeartbeatRetries})"); // 添加延时,给SDK实例初始化一些时间 if (retry > 0) { int retryDelay = 500 + (retry - 1) * 300; // 递增延时 - Console.WriteLine($"等待{retryDelay}ms后重试..."); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 等待{retryDelay}ms后重试..."); Thread.Sleep(retryDelay); } @@ -2658,18 +3303,18 @@ namespace JoyD.Windows.CS.Toprie int heartbeatResult = newSdk.Heartbeat(); if (heartbeatResult > 0) { - Console.WriteLine("心跳检测成功!"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 心跳检测成功!"); isConnected = true; break; } else { - Console.WriteLine($"心跳检测失败,返回值: {heartbeatResult}"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 心跳检测失败,返回值: {heartbeatResult}"); } } catch (Exception ex) { - Console.WriteLine($"心跳检测异常: {ex.Message},堆栈: {ex.StackTrace}"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 心跳检测异常: {ex.Message},堆栈: {ex.StackTrace}"); } } @@ -2678,80 +3323,125 @@ namespace JoyD.Windows.CS.Toprie // 连接成功,进行额外验证 try { - Console.WriteLine("进行额外连接验证..."); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 进行额外连接验证..."); // 再次发送心跳包确保连接稳定 int finalResult = newSdk.Heartbeat(); if (finalResult > 0) { // 验证成功后,安全地更新SDK实例 Interlocked.Exchange(ref _a8Sdk, newSdk); - Console.WriteLine($"使用IP地址 {_deviceIp} 重连成功"); - _currentDeviceId = 1; // 临时ID,确保状态更新正确 - UpdateConnectionStatus(ConnectionStatus.Connected, $"设备 {_deviceIp} 连接成功"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 使用IP地址 {deviceIp} 重连成功"); + + // 线程安全地更新设备ID + lock (_lockObject) + { + _currentDeviceId = 1; // 临时ID,确保状态更新正确 + } + + UpdateConnectionStatus(ConnectionStatus.Connected, $"设备 {deviceIp} 连接成功"); StartConnectionCheck(); connectionSuccessful = true; } else { - Console.WriteLine($"最终验证失败,返回值: {finalResult}"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 最终验证失败,返回值: {finalResult}"); } } catch (Exception ex) { - Console.WriteLine($"连接验证异常: {ex.Message}"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 连接验证异常: {ex.Message}"); } } // 如果连接不成功,释放资源 if (!connectionSuccessful) { - Console.WriteLine($"使用IP地址 {_deviceIp} 重连失败,所有心跳尝试都未成功"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 使用IP地址 {deviceIp} 重连失败,所有心跳尝试都未成功"); // 确保资源被释放 try { newSdk = null; } catch { } } } else { - Console.WriteLine($"IP地址 {_deviceIp} 不可达,等待设备上线"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - IP地址 {deviceIp} 不可达,等待设备上线"); } } catch (Exception ex) { - Console.WriteLine($"使用IP地址重连异常: {ex.Message},堆栈: {ex.StackTrace}"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 使用IP地址重连异常: {ex.Message},堆栈: {ex.StackTrace}"); } } // 如果IP地址连接失败,再尝试使用设备ID连接(保持兼容性) - // 但如果已经在连接中,则跳过 - if (!connectionSuccessful && _currentDeviceId != -1 && !_isConnecting) + // 但如果已经在连接中,则跳过 + if (!connectionSuccessful) { - Console.WriteLine($"尝试使用设备ID {_currentDeviceId} 连接"); - ConnectDevice(_currentDeviceId); - if (_connectionStatus == ConnectionStatus.Connected) + int currentDeviceId = -1; + bool isConnecting = false; + lock (_lockObject) { - connectionSuccessful = true; + currentDeviceId = _currentDeviceId; + isConnecting = _isConnecting; + } + + if (currentDeviceId != -1 && !isConnecting) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 尝试使用设备ID {currentDeviceId} 连接"); + ConnectDevice(currentDeviceId); + + // 线程安全地检查连接状态 + ConnectionStatus status = ConnectionStatus.Disconnected; + lock (_lockObject) + { + status = _connectionStatus; + } + if (status == ConnectionStatus.Connected) + { + connectionSuccessful = true; + } } } // 如果没有保存的设备ID,但有搜索到的设备,尝试连接第一个 - // 但如果已经在连接中,则跳过 - if (!connectionSuccessful && _deviceIds != null && _deviceIds.Count > 0 && !_isConnecting) + // 但如果已经在连接中,则跳过 + if (!connectionSuccessful) { - Console.WriteLine($"尝试使用搜索到的设备列表中的第一个设备"); - if (int.TryParse(_deviceIds[0], out int deviceId)) + bool isConnecting = false; + List deviceIds = null; + lock (_lockObject) { - ConnectDevice(deviceId); + isConnecting = _isConnecting; + if (_deviceIds != null) + { + deviceIds = new List(_deviceIds); + } } - if (_connectionStatus == ConnectionStatus.Connected) + + if (deviceIds != null && deviceIds.Count > 0 && !isConnecting) { - connectionSuccessful = true; + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 尝试使用搜索到的设备列表中的第一个设备"); + if (int.TryParse(deviceIds[0], out int deviceId)) + { + ConnectDevice(deviceId); + } + + // 线程安全地检查连接状态 + ConnectionStatus status = ConnectionStatus.Disconnected; + lock (_lockObject) + { + status = _connectionStatus; + } + if (status == ConnectionStatus.Connected) + { + connectionSuccessful = true; + } } } // 如果连接成功,停止重连定时器 if (connectionSuccessful) { - Console.WriteLine("设备连接成功,停止自动重连"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 设备连接成功,停止自动重连"); StopAutoReconnect(); return; } @@ -2760,8 +3450,8 @@ namespace JoyD.Windows.CS.Toprie UpdateConnectionStatus(ConnectionStatus.Disconnected, "所有连接尝试失败"); // 改进的间隔递增策略,避免频繁重连导致的网络压力 - int retryInterval = Math.Min(_reconnectInterval * (1 + _currentReconnectAttempt / 5), 20000); // 最大20秒 - Console.WriteLine($"调整重连间隔为 {retryInterval}ms"); + int retryInterval = Math.Min(_reconnectInterval * (1 + currentAttempts / 5), 20000); // 最大20秒 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 调整重连间隔为 {retryInterval}ms"); // 安全地更新定时器 System.Threading.Timer currentTimer = _reconnectTimer; @@ -2774,13 +3464,13 @@ namespace JoyD.Windows.CS.Toprie } catch (ObjectDisposedException) { - Console.WriteLine("定时器已被释放,无法更新"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 定时器已被释放,无法更新"); } } } catch (Exception ex) { - Console.WriteLine($"重连回调函数发生异常: {ex.Message},堆栈: {ex.StackTrace}"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 重连回调函数发生异常: {ex.Message},堆栈: {ex.StackTrace}"); // 确保定时器继续工作,防止重连机制中断 System.Threading.Timer currentTimer = _reconnectTimer; if (currentTimer != null) @@ -2792,14 +3482,15 @@ namespace JoyD.Windows.CS.Toprie } catch (ObjectDisposedException) { - Console.WriteLine("定时器已被释放,无法恢复"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 定时器已被释放,无法恢复"); } } } finally { // 无论如何都要重置重入标志,确保后续重连可以正常触发 - _isReconnecting = 0; + Interlocked.Exchange(ref _isReconnecting, 0); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] ReconnectCallback() - 执行完成"); } } @@ -2809,44 +3500,78 @@ namespace JoyD.Windows.CS.Toprie /// private void StartHeartbeat() { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartHeartbeat() - 开始执行"); + // 在设计模式下,跳过实际的心跳检测 if (IsDesignMode) { - Log("设计模式下跳过实际的心跳检测"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartHeartbeat() - 设计模式下跳过实际的心跳检测"); + return; + } + + if (_isDisposed) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartHeartbeat() - 对象已释放,无法启动心跳检测"); return; } - // 停止现有的心跳定时器 - StopHeartbeat(); - - // 创建新的心跳定时器 - _heartbeatTimer = new System.Threading.Timer(HeartbeatCallback, null, 0, _heartbeatInterval); + try + { + // 停止现有的心跳定时器 + StopHeartbeat(); + + // 创建新的心跳定时器 + System.Threading.Timer newTimer = new System.Threading.Timer(HeartbeatCallback, null, 0, _heartbeatInterval); + Interlocked.Exchange(ref _heartbeatTimer, newTimer); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartHeartbeat() - 心跳检测已启动,间隔: {_heartbeatInterval}ms"); + } + catch (Exception ex) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartHeartbeat() - 创建心跳定时器异常: {ex.Message},堆栈: {ex.StackTrace}"); + OnConnectionException(new ConnectionExceptionEventArgs(ex, "启动心跳检测失败")); + } + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StartHeartbeat() - 执行完成"); } /// /// 停止心跳检测 /// private void StopHeartbeat() - { + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopHeartbeat() - 开始执行"); + try - { + { // 使用Interlocked.Exchange确保线程安全 System.Threading.Timer timerToDispose = Interlocked.Exchange(ref _heartbeatTimer, null); if (timerToDispose != null) - { - // 立即停止定时器,避免回调执行 - timerToDispose.Change(Timeout.Infinite, Timeout.Infinite); - // 安全释放定时器资源 - timerToDispose.Dispose(); - Console.WriteLine("心跳检测已停止"); + { + try + { + // 立即停止定时器,避免回调执行 + timerToDispose.Change(Timeout.Infinite, Timeout.Infinite); + // 安全释放定时器资源 + timerToDispose.Dispose(); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopHeartbeat() - 心跳检测已停止"); + } + catch (ObjectDisposedException) + { + // 如果定时器已被释放,无需再处理 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopHeartbeat() - 定时器已被释放"); + } + } + else + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopHeartbeat() - 心跳定时器不存在,无需停止"); } } catch (Exception ex) - { - Console.WriteLine($"停止心跳检测异常: {ex.Message}"); + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopHeartbeat() - 停止心跳检测异常: {ex.Message},堆栈: {ex.StackTrace}"); // 确保即使异常,引用也被清空 - _heartbeatTimer = null; + Interlocked.Exchange(ref _heartbeatTimer, null); } + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] StopHeartbeat() - 执行完成"); } /// @@ -2854,7 +3579,16 @@ namespace JoyD.Windows.CS.Toprie /// /// 定时器状态 private void HeartbeatCallback(object state) - { + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 开始执行"); + + // 检查对象是否已释放 + if (_isDisposed) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 对象已释放,退出心跳检测"); + return; + } + try { // 检查设备是否可达,使用改进的PingDevice方法 @@ -2872,14 +3606,14 @@ namespace JoyD.Windows.CS.Toprie if (i < pingRetries) { - Console.WriteLine($"Ping设备失败,{300 * (i + 1)}ms后重试..."); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - Ping设备失败,{300 * (i + 1)}ms后重试..."); Thread.Sleep(300 * (i + 1)); // 递增延时 } } if (!deviceReachable) { - Console.WriteLine("心跳检测失败,设备不可达"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 心跳检测失败,设备不可达"); UpdateConnectionStatus(ConnectionStatus.Disconnected, "心跳检测失败,设备不可达"); // 如果启用了自动重连,开始重连 @@ -2890,12 +3624,33 @@ namespace JoyD.Windows.CS.Toprie return; } + // 检查是否最近收到过数据 + bool recentlyReceivedData = false; + if (_lastDataReceivedTime != DateTime.MinValue) + { + TimeSpan timeSinceLastData = DateTime.Now - _lastDataReceivedTime; + recentlyReceivedData = timeSinceLastData.TotalMilliseconds < DataReceivedTimeout; + + if (recentlyReceivedData) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 最近{timeSinceLastData.TotalMilliseconds:F0}ms内收到过数据,跳过心跳检测"); + // 更新连接状态为正常 + if (_connectionStatus != ConnectionStatus.Connected) + { + UpdateConnectionStatus(ConnectionStatus.Connected, "最近收到数据,连接正常"); + } + return; + } + } + + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 长时间未收到数据,执行心跳检测"); + // 使用SDK的Heartbeat方法进行心跳检测,添加重试机制 A8SDK currentSdk = _a8Sdk; if (currentSdk != null) { bool heartbeatSuccessful = false; - int heartbeatRetries = 1; + int heartbeatRetries = 2; // 修改为2次重试,总共3次尝试 for (int i = 0; i <= heartbeatRetries; i++) { @@ -2905,32 +3660,32 @@ namespace JoyD.Windows.CS.Toprie if (heartbeatResult > 0) { heartbeatSuccessful = true; - Console.WriteLine("心跳检测成功"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 心跳检测成功 (第{i+1}次尝试)"); // 定期更新连接状态,表明连接正常 if (_connectionStatus != ConnectionStatus.Connected) { UpdateConnectionStatus(ConnectionStatus.Connected, "设备连接已恢复"); } - break; + break; // 一次成功就立即返回,不再重试 } else { - Console.WriteLine($"SDK心跳检测失败,返回值: {heartbeatResult}"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - SDK心跳检测失败 (第{i+1}次尝试),返回值: {heartbeatResult}"); if (i < heartbeatRetries) { - Console.WriteLine("300ms后重试心跳检测..."); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 300ms后重试心跳检测..."); Thread.Sleep(300); } } } catch (Exception ex) { - Console.WriteLine($"心跳检测异常: {ex.Message}"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 心跳检测异常 (第{i+1}次尝试): {ex.Message},堆栈: {ex.StackTrace}"); if (i < heartbeatRetries) { - Console.WriteLine("300ms后重试心跳检测..."); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 300ms后重试心跳检测..."); Thread.Sleep(300); } } @@ -2938,7 +3693,7 @@ namespace JoyD.Windows.CS.Toprie if (!heartbeatSuccessful) { - Console.WriteLine("SDK心跳检测失败,连接可能已断开"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - SDK心跳检测失败,连接可能已断开"); UpdateConnectionStatus(ConnectionStatus.Disconnected, "SDK心跳检测失败,连接已断开"); // 如果启用了自动重连,开始重连 @@ -2950,7 +3705,7 @@ namespace JoyD.Windows.CS.Toprie } else { - Console.WriteLine("SDK实例不存在,尝试重连"); + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - SDK实例不存在,尝试重连"); UpdateConnectionStatus(ConnectionStatus.Disconnected, "SDK实例不存在"); if (_isAutoReconnectEnabled) @@ -2960,14 +3715,34 @@ namespace JoyD.Windows.CS.Toprie } } catch (Exception ex) - { - Console.WriteLine($"心跳检测时发生异常: {ex.Message},堆栈: {ex.StackTrace}"); - OnConnectionException(new ConnectionExceptionEventArgs(ex, "心跳检测失败")); + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 心跳检测时发生异常: {ex.Message},堆栈: {ex.StackTrace}"); + + // 触发连接异常事件 + try + { + if (!_isDisposed) + { + OnConnectionException(new ConnectionExceptionEventArgs(ex, "心跳检测失败")); + } + } + catch (Exception ex2) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 触发异常事件失败: {ex2.Message}"); + } // 异常情况下也尝试重连 - if (_isAutoReconnectEnabled) - { - StartAutoReconnect(); + try + { + if (!_isDisposed && _isAutoReconnectEnabled) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 异常情况下触发自动重连"); + StartAutoReconnect(); + } + } + catch (Exception ex3) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] HeartbeatCallback() - 启动自动重连失败: {ex3.Message}"); } } } @@ -3237,57 +4012,101 @@ namespace JoyD.Windows.CS.Toprie /// /// 是否释放托管资源 protected virtual void Dispose(bool disposing) - { - if (!_disposed) + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Dispose({disposing}) - 开始执行"); + + // 使用锁确保线程安全 + lock (_lockObject) { - if (disposing) + if (!_disposed) { - // 释放托管资源 - StopAutoReconnect(); - StopConnectionCheck(); - StopHeartbeat(); - StopAllImageReceivers(); - _stopRequested.Dispose(); - } + _disposed = true; + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Dispose() - 开始清理资源"); - // 安全释放SDK实例,避免内存访问冲突 - try - { - if (_a8Sdk != null) - { - Console.WriteLine("释放SDK实例资源"); - // 先设置为null,避免在Dispose过程中的访问 - _a8Sdk = null; + try + { + // 首先停止所有活动的线程和定时器 + Log("[线程安全] Dispose() - 停止所有活动组件"); + + // 使用单独的try-catch确保每个组件的停止都不会影响其他组件 + try { StopHeartbeat(); } catch (Exception ex) { Log($"停止心跳异常: {ex.Message}"); } + try { StopConnectionCheck(); } catch (Exception ex) { Log($"停止连接检查异常: {ex.Message}"); } + // 直接调用内部方法避免嵌套锁 + try { StopAutoReconnectInternal(); } catch (Exception ex) { Log($"停止自动重连异常: {ex.Message}"); } + + if (disposing) + { + // 释放托管资源 + Log("[托管] Dispose() - 释放托管资源"); + + try { StopAllImageReceivers(); } catch (Exception ex) { Log($"停止图像接收器异常: {ex.Message}"); } + + // 安全释放信号量 + try + { + if (_stopRequested != null) + { + _stopRequested.Dispose(); + _stopRequested = null; + Log("[托管] Dispose() - 成功释放_stopRequested信号量"); + } + } + catch (Exception ex) + { + Log($"[托管] 释放_stopRequested异常: {ex.Message}"); + } + } + + // 安全释放SDK实例,避免内存访问冲突 + Log("[非托管] Dispose() - 释放SDK实例资源"); + A8SDK sdkToDispose = Interlocked.Exchange(ref _a8Sdk, null); + if (sdkToDispose != null) + { + try + { + // 这里可以添加SDK实例的清理代码 + // sdkToDispose.Close(); // 假设SDK有关闭方法 + Log("[非托管] Dispose() - SDK实例资源已标记为null"); + } + catch (Exception ex) + { + Log($"[非托管] 释放SDK实例异常: {ex.Message}"); + } + } + + // 释放全局SDK资源,使用try-catch避免异常传播 + try + { + Log("[非托管] Dispose() - 释放SDK全局资源"); + if (_isInitialized) + { + // 如果SDK支持,调用静态方法释放全局资源 + // A8SDK.SDK_destroy(); + _isInitialized = false; + Log("[非托管] Dispose() - 成功重置_isInitialized标志"); + } + } + catch (Exception ex) + { + Log($"[非托管] 释放SDK全局资源异常: {ex.Message}"); + } + + // 重置所有状态标志,确保对象处于一致的已释放状态 + _connectionStatus = ConnectionStatus.Disconnected; + _currentDeviceId = -1; + + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Dispose() - 资源清理完成"); + } + catch (Exception ex) + { + // 捕获所有可能的异常,确保_disposed标志设置成功 + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Dispose() - 发生异常: {ex.Message}\n{ex.StackTrace}"); } } - catch (Exception ex) - { - Console.WriteLine($"释放SDK实例异常: {ex.Message}"); - // 即使异常也确保引用被清空 - _a8Sdk = null; + else + { + Log($"[{DateTime.Now:HH:mm:ss.fff}] [线程:{Thread.CurrentThread.ManagedThreadId}] Dispose() - 对象已被释放,跳过重复清理"); } - - // 释放全局SDK资源,使用try-catch避免异常传播 - try - { - Console.WriteLine("释放SDK全局资源"); - if (_isInitialized) - { - // 如果SDK支持,调用静态方法释放全局资源 - // A8SDK.SDK_destroy(); - } - } - catch (Exception ex) - { - Console.WriteLine($"释放SDK全局资源异常: {ex.Message}"); - } - - // 释放非托管资源 - _isInitialized = false; - _connectionStatus = ConnectionStatus.Disconnected; - _currentDeviceId = -1; - - _disposed = true; } } diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/UdpCommunicationManager.cs b/Windows/CS/Framework4.0/Toprie/Toprie/UdpCommunicationManager.cs index 615d5f5..3b8957f 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/UdpCommunicationManager.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/UdpCommunicationManager.cs @@ -263,6 +263,18 @@ namespace JoyD.Windows.CS.Toprie return tcs.Task; } + /// + /// UDP请求结果枚举 + /// + public enum RequestResult + { + Success, + Timeout, + NetworkError, + ProcessingError, + InvalidResponse + } + /// /// 同步发送UDP请求 /// @@ -270,19 +282,131 @@ namespace JoyD.Windows.CS.Toprie /// 要发送的数据 /// 目标端口,默认为18890 /// 超时时间(毫秒),默认为500 + /// 返回的响应数据 + /// 请求结果 + public RequestResult SendRequest(string targetIp, byte[] data, out byte[] response, int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT) + { + response = null; + try + { + var task = SendRequestAsync(targetIp, data, port, timeout); + bool completed = task.Wait(timeout); + if (completed) + { + response = task.Result; + if (response != null) + { + return RequestResult.Success; + } + return RequestResult.NetworkError; + } + Console.WriteLine($"UDP请求执行超时({timeout}ms)"); + return RequestResult.Timeout; + } + catch (TimeoutException) + { + Console.WriteLine($"UDP请求执行超时异常"); + return RequestResult.Timeout; + } + catch (Exception ex) + { + Console.WriteLine($"发送UDP请求时发生错误: {ex.Message}"); + return RequestResult.ProcessingError; + } + } + + /// + /// 同步发送UDP请求(兼容旧版本) + /// + /// 目标IP地址 + /// 要发送的数据 + /// 目标端口,默认为18890 + /// 超时时间(毫秒),默认为500 /// 响应数据,如果超时则返回null public byte[] SendRequest(string targetIp, byte[] data, int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT) { + SendRequest(targetIp, data, out byte[] response, port, timeout); + return response; + } + + /// + /// 异步发送字符串命令的UDP请求 + /// + /// 目标IP地址 + /// 要发送的命令字符串 + /// 目标端口,默认为18890 + /// 超时时间(毫秒),默认为500 + /// 包含响应字符串的Task + public Task SendRequestAsync(string targetIp, string command, int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT) + { + byte[] data = Encoding.ASCII.GetBytes(command); + Task dataTask = SendRequestAsync(targetIp, data, port, timeout); + + // 创建一个新的Task用于返回字符串结果 + TaskCompletionSource tcs = new TaskCompletionSource(); + + dataTask.ContinueWith(task => { + if (task.IsFaulted) + { + tcs.SetException(task.Exception); + } + else if (task.IsCanceled) + { + tcs.SetCanceled(); + } + else + { + byte[] result = task.Result; + string stringResult = result != null ? Encoding.ASCII.GetString(result) : null; + tcs.SetResult(stringResult); + } + }); + + return tcs.Task; + } + + /// + /// 同步发送字符串命令的UDP请求 + /// + /// 目标IP地址 + /// 要发送的命令 + /// 超时时间(毫秒) + /// 返回的响应内容 + /// 请求结果 + public RequestResult SendRequest(string targetIp, string command, int timeoutMs, out string response) + { + response = null; try { - var task = SendRequestAsync(targetIp, data, port, timeout); - task.Wait(timeout); - return task.Result; + var task = SendRequestAsync(targetIp, command, DEFAULT_UDP_PORT, timeoutMs); + bool completed = task.Wait(timeoutMs + 50); // 额外添加50ms作为缓冲 + if (completed) + { + response = task.Result; + if (response != null) + { + // 验证响应格式是否符合预期 + if (response.Length > 0 && (response.StartsWith("+RET:") || response.Contains(":"))) + { + return RequestResult.Success; + } + Console.WriteLine($"命令 '{command}' 收到无效响应: '{response}'"); + return RequestResult.InvalidResponse; + } + return RequestResult.NetworkError; + } + Console.WriteLine($"命令 '{command}' 执行超时({timeoutMs}ms)"); + return RequestResult.Timeout; + } + catch (TimeoutException) + { + Console.WriteLine($"命令 '{command}' 执行超时异常"); + return RequestResult.Timeout; } catch (Exception ex) { - Console.WriteLine($"同步发送UDP请求异常: {ex.Message}"); - return null; + Console.WriteLine($"发送命令 '{command}' 时发生错误: {ex.Message}"); + return RequestResult.ProcessingError; } } diff --git a/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs b/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs index 6fc3661..9930969 100644 --- a/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs +++ b/Windows/CS/Framework4.0/Toprie/Toprie/V8.cs @@ -218,11 +218,11 @@ namespace JoyD.Windows.CS.Toprie try { - // 使用UDP通信管理器发送请求 - byte[] responseBytes = UdpCommunicationManager.Instance.SendRequest(deviceIp, - Encoding.ASCII.GetBytes(cmd), 18890, 200); + // 使用UDP通信管理器发送请求,获取详细的请求结果 + var result = UdpCommunicationManager.Instance.SendRequest(deviceIp, + Encoding.ASCII.GetBytes(cmd), out byte[] responseBytes, 18890, 200); - if (responseBytes != null) + if (result == UdpCommunicationManager.RequestResult.Success && responseBytes != null) { response = Encoding.ASCII.GetString(responseBytes); Console.WriteLine($"UDP命令已发送: {cmd}"); @@ -232,7 +232,25 @@ namespace JoyD.Windows.CS.Toprie } else { - Console.WriteLine($"UDP命令发送后未收到响应或超时: {cmd}"); + // 根据不同的结果类型提供更详细的信息 + switch (result) + { + case UdpCommunicationManager.RequestResult.Timeout: + Console.WriteLine($"UDP命令 '{cmd}' 发送后超时"); + break; + case UdpCommunicationManager.RequestResult.NetworkError: + Console.WriteLine($"UDP命令 '{cmd}' 网络错误"); + break; + case UdpCommunicationManager.RequestResult.InvalidResponse: + Console.WriteLine($"UDP命令 '{cmd}' 收到无效响应"); + break; + case UdpCommunicationManager.RequestResult.ProcessingError: + Console.WriteLine($"UDP命令 '{cmd}' 处理错误"); + break; + default: + Console.WriteLine($"UDP命令 '{cmd}' 发送后未收到有效响应"); + break; + } return false; } @@ -464,6 +482,8 @@ namespace JoyD.Windows.CS.Toprie } } + private int _lastKnownColorPlate = 0; // 保存最后已知的色板值 + public int Color_plate { get @@ -475,14 +495,20 @@ namespace JoyD.Windows.CS.Toprie if (SendCommand(command, out string response)) { - return ParseResponseValue(response); + int parsedValue = ParseResponseValue(response); + if (parsedValue != 0 || response != null) // 确保至少解析成功或有响应 + { + _lastKnownColorPlate = parsedValue; + return parsedValue; + } } - return 0; // 默认色板 + Console.WriteLine("获取色板失败,返回上次已知值"); + return _lastKnownColorPlate; // 返回上次已知值 } catch (Exception ex) { - Console.WriteLine($"获取色板失败: {ex.Message}"); - return 0; + Console.WriteLine($"获取色板异常: {ex.Message},返回上次已知值"); + return _lastKnownColorPlate; } } set @@ -492,18 +518,31 @@ namespace JoyD.Windows.CS.Toprie // 使用SDK格式设置色板: ip:param_mode,param_value$ string command = $"{deviceIp}:{(int)CMD_TYPE.SET_COLOR_PLATE},{value}$"; - if (SendCommand(command, out string response)) + bool success = SendCommand(command, out string response); + if (success && response != null) { - // 验证响应 - if (response != null) + // 验证响应是否包含成功标记 + bool responseValid = response.Contains("+RET:") && + (!response.Contains("error") || !response.Contains("失败")); + + if (responseValid) { - Console.WriteLine("设置色板成功"); + Console.WriteLine($"设置色板成功: {value}"); + _lastKnownColorPlate = value; // 更新最后已知值 } + else + { + Console.WriteLine($"设置色板响应验证失败: {response}"); + } + } + else + { + Console.WriteLine($"设置色板失败: 命令发送失败或超时"); } } catch (Exception ex) { - Console.WriteLine($"设置色板失败: {ex.Message}"); + Console.WriteLine($"设置色板异常: {ex.Message}"); } } }