重连
This commit is contained in:
@@ -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);
|
||||
@@ -571,27 +571,73 @@ namespace JoyD.Windows.CS.Toprie
|
||||
/// </summary>
|
||||
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<ConnectionStatusChangedEventArgs>(args =>
|
||||
{
|
||||
// 再次检查控件状态,防止在异步调用期间控件被释放
|
||||
if (!this.IsDisposed && !this.Disposing)
|
||||
{
|
||||
HandleConnectionStatusChanged(args);
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
else
|
||||
{
|
||||
Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 异步调用期间控件已释放,跳过处理");
|
||||
}
|
||||
}), e);
|
||||
}
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -739,35 +785,92 @@ namespace JoyD.Windows.CS.Toprie
|
||||
/// </summary>
|
||||
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线程上显示错误
|
||||
// 创建局部变量保存错误消息,避免闭包问题
|
||||
string errorMsg = uiErrorMessage;
|
||||
|
||||
// 使用BeginInvoke代替Invoke,避免可能的死锁问题
|
||||
this.BeginInvoke(new Action(() =>
|
||||
{
|
||||
// 记录异常日志
|
||||
Console.WriteLine($"连接异常发生于 {DateTime.Now}: {e.Message}\n{e.Exception.Message}\n{e.Exception.StackTrace}");
|
||||
|
||||
ShowError($"连接异常: {e.Message}");
|
||||
}));
|
||||
}
|
||||
catch (ObjectDisposedException)
|
||||
// 再次检查控件状态,防止在异步调用期间控件被释放
|
||||
if (!this.IsDisposed && !this.Disposing)
|
||||
{
|
||||
// 捕获控件已释放异常,避免程序崩溃
|
||||
Console.WriteLine("控件已释放,跳过异常处理");
|
||||
try
|
||||
{
|
||||
ShowError(errorMsg);
|
||||
}
|
||||
catch (Exception showEx)
|
||||
{
|
||||
Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 显示错误消息异常: {showEx.Message}");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// 记录异常日志
|
||||
Console.WriteLine($"连接异常发生于 {DateTime.Now}: {e.Message}\n{e.Exception.Message}\n{e.Exception.StackTrace}");
|
||||
|
||||
ShowError($"连接异常: {e.Message}");
|
||||
Console.WriteLine($"[{DateTime.Now:HH:mm:ss.fff}] 异步调用期间控件已释放,跳过错误显示");
|
||||
}
|
||||
}));
|
||||
}
|
||||
catch (ObjectDisposedException ode)
|
||||
{
|
||||
// 捕获控件已释放异常,避免程序崩溃
|
||||
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线程上处理
|
||||
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}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -263,6 +263,18 @@ namespace JoyD.Windows.CS.Toprie
|
||||
return tcs.Task;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// UDP请求结果枚举
|
||||
/// </summary>
|
||||
public enum RequestResult
|
||||
{
|
||||
Success,
|
||||
Timeout,
|
||||
NetworkError,
|
||||
ProcessingError,
|
||||
InvalidResponse
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步发送UDP请求
|
||||
/// </summary>
|
||||
@@ -270,19 +282,131 @@ namespace JoyD.Windows.CS.Toprie
|
||||
/// <param name="data">要发送的数据</param>
|
||||
/// <param name="port">目标端口,默认为18890</param>
|
||||
/// <param name="timeout">超时时间(毫秒),默认为500</param>
|
||||
/// <param name="response">返回的响应数据</param>
|
||||
/// <returns>请求结果</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步发送UDP请求(兼容旧版本)
|
||||
/// </summary>
|
||||
/// <param name="targetIp">目标IP地址</param>
|
||||
/// <param name="data">要发送的数据</param>
|
||||
/// <param name="port">目标端口,默认为18890</param>
|
||||
/// <param name="timeout">超时时间(毫秒),默认为500</param>
|
||||
/// <returns>响应数据,如果超时则返回null</returns>
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步发送字符串命令的UDP请求
|
||||
/// </summary>
|
||||
/// <param name="targetIp">目标IP地址</param>
|
||||
/// <param name="command">要发送的命令字符串</param>
|
||||
/// <param name="port">目标端口,默认为18890</param>
|
||||
/// <param name="timeout">超时时间(毫秒),默认为500</param>
|
||||
/// <returns>包含响应字符串的Task</returns>
|
||||
public Task<string> SendRequestAsync(string targetIp, string command, int port = DEFAULT_UDP_PORT, int timeout = DEFAULT_TIMEOUT)
|
||||
{
|
||||
byte[] data = Encoding.ASCII.GetBytes(command);
|
||||
Task<byte[]> dataTask = SendRequestAsync(targetIp, data, port, timeout);
|
||||
|
||||
// 创建一个新的Task用于返回字符串结果
|
||||
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步发送字符串命令的UDP请求
|
||||
/// </summary>
|
||||
/// <param name="targetIp">目标IP地址</param>
|
||||
/// <param name="command">要发送的命令</param>
|
||||
/// <param name="timeoutMs">超时时间(毫秒)</param>
|
||||
/// <param name="response">返回的响应内容</param>
|
||||
/// <returns>请求结果</returns>
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user