异步连接

This commit is contained in:
zqm
2026-01-05 14:31:29 +08:00
parent 652b53ff3e
commit 6c30ab376b
4 changed files with 105 additions and 40 deletions

View File

@@ -501,15 +501,24 @@ namespace JoyD.Windows.CS.Toprie
// 将设计模式状态传递给DeviceManager // 将设计模式状态传递给DeviceManager
UpdateDesignModeStatus(); UpdateDesignModeStatus();
// 初始化图像缓冲区
InitializeImageBuffer();
// 加载保存的菜单配置
LoadMenuConfig();
// 初始化Ping定时器 // 初始化Ping定时器
_pingTimer = new System.Threading.Timer(PingTimer_Tick, null, Timeout.Infinite, Timeout.Infinite); _pingTimer = new System.Threading.Timer(PingTimer_Tick, null, Timeout.Infinite, Timeout.Infinite);
// 异步初始化图像缓冲区和加载菜单配置避免阻塞UI线程
ThreadPool.QueueUserWorkItem(delegate
{
try
{
InitializeImageBuffer();
LoadMenuConfig();
Console.WriteLine("图像缓冲区和菜单配置已异步初始化完成");
}
catch (Exception ex)
{
Console.WriteLine($"异步初始化失败: {ex.Message}");
}
});
// 只有在非设计模式下才初始化设备管理器和错误定时器 // 只有在非设计模式下才初始化设备管理器和错误定时器
if (!DesignMode) if (!DesignMode)
{ {
@@ -574,11 +583,22 @@ namespace JoyD.Windows.CS.Toprie
// 设置静态属性 // 设置静态属性
DeviceManager.MaxReconnectAttempts = 5; DeviceManager.MaxReconnectAttempts = 5;
// 初始化时加载配置文件,只执行一次 // 异步加载配置文件,避免阻塞主线程
if (!_isConfigLoaded) if (!_isConfigLoaded)
{
ThreadPool.QueueUserWorkItem(delegate
{
try
{ {
LoadAllConfigs(); LoadAllConfigs();
_isConfigLoaded = true; _isConfigLoaded = true;
Console.WriteLine("配置文件已异步加载完成");
}
catch (Exception ex)
{
Console.WriteLine($"异步加载配置文件失败: {ex.Message}");
}
});
} }
// 注册图像接收事件 // 注册图像接收事件
@@ -663,10 +683,6 @@ namespace JoyD.Windows.CS.Toprie
} }
} }
} }
/// <summary> /// <summary>
/// 启动相机 /// 启动相机
/// </summary> /// </summary>
@@ -1873,7 +1889,7 @@ namespace JoyD.Windows.CS.Toprie
{ {
using (var ping = new System.Net.NetworkInformation.Ping()) using (var ping = new System.Net.NetworkInformation.Ping())
{ {
var reply = ping.Send(ipAddress, 2000); // 2秒超时 var reply = ping.Send(ipAddress, 1000); // 1秒超时与DeviceManager保持一致
return reply != null && reply.Status == System.Net.NetworkInformation.IPStatus.Success; return reply != null && reply.Status == System.Net.NetworkInformation.IPStatus.Success;
} }
} }

View File

@@ -357,6 +357,41 @@ namespace JoyD.Windows.CS.Toprie
return false; return false;
} }
} }
/// <summary>
/// 带超时的TCP连接方法
/// </summary>
/// <param name="client">TCP客户端</param>
/// <param name="host">主机地址</param>
/// <param name="port">端口号</param>
/// <param name="timeoutMs">超时时间(毫秒)</param>
/// <returns>连接是否成功</returns>
private bool ConnectWithTimeout(TcpClient client, string host, int port, int timeoutMs)
{
try
{
// 使用异步连接并等待超时
IAsyncResult result = client.BeginConnect(host, port, null, null);
bool success = result.AsyncWaitHandle.WaitOne(timeoutMs, false);
if (success)
{
client.EndConnect(result);
return true;
}
else
{
// 连接超时,关闭客户端
client.Close();
return false;
}
}
catch
{
// 发生异常,关闭客户端
client.Close();
return false;
}
}
private ManualResetEvent _stopTemperatureEvent; private ManualResetEvent _stopTemperatureEvent;
private const int TEMPERATURE_TCP_PORT = 8081; // 温度数据TCP端口 - 修正为热像仪SDK文档中指定的端口 private const int TEMPERATURE_TCP_PORT = 8081; // 温度数据TCP端口 - 修正为热像仪SDK文档中指定的端口
@@ -1061,7 +1096,7 @@ namespace JoyD.Windows.CS.Toprie
try try
{ {
Console.WriteLine($"正在ping设备IP: {ipAddress},检查网络可达性..."); Console.WriteLine($"正在ping设备IP: {ipAddress},检查网络可达性...");
var reply = ping.Send(ipAddress, 2000); // 增加超时时间到2秒 var reply = ping.Send(ipAddress, 1000); // 降低超时时间到1秒提高响应速度
bool isReachable = reply != null && reply.Status == System.Net.NetworkInformation.IPStatus.Success; bool isReachable = reply != null && reply.Status == System.Net.NetworkInformation.IPStatus.Success;
Console.WriteLine($"Ping结果: {(isReachable ? "" : "")}"); Console.WriteLine($"Ping结果: {(isReachable ? "" : "")}");
return isReachable; return isReachable;
@@ -1526,16 +1561,41 @@ namespace JoyD.Windows.CS.Toprie
ReceiveBufferSize = 65536 // 64KB ReceiveBufferSize = 65536 // 64KB
}; };
Log($"正在连接到温度数据端口 {temperaturePort}..."); const int CONNECTION_TIMEOUT = 3000; // 3秒连接超时
_temperatureTcpClient.Connect(deviceIp, temperaturePort); Log($"正在连接到温度数据端口 {temperaturePort}... (超时: {CONNECTION_TIMEOUT}ms)");
// 使用带超时的连接方法
if (ConnectWithTimeout(_temperatureTcpClient, deviceIp, temperaturePort, CONNECTION_TIMEOUT))
{
Log("温度数据TCP连接成功"); Log("温度数据TCP连接成功");
// 连接成功,重置重连计数
_currentReconnectAttempt = 0;
}
else
{
Log($"TCP连接超时{CONNECTION_TIMEOUT}ms内未连接成功");
_temperatureTcpClient = null;
// 增加重连计数,使用指数退避策略
_currentReconnectAttempt++;
// 重连间隔1秒 * 2^(重连次数)最大10秒
int retryDelay = Math.Min(1000 * (int)Math.Pow(2, _currentReconnectAttempt), 10000);
Log($"{retryDelay}ms后将尝试重新连接... (尝试 {_currentReconnectAttempt}次)");
Thread.Sleep(retryDelay);
continue;
}
} }
catch (Exception ex) catch (Exception ex)
{ {
Log($"TCP连接或初始化失败: {ex.Message}"); Log($"TCP连接或初始化失败: {ex.Message}");
_temperatureTcpClient = null; _temperatureTcpClient = null;
// 连接失败后等待一段时间再重试
Thread.Sleep(LONG_SLEEP_MS); // 增加重连计数,使用指数退避策略
_currentReconnectAttempt++;
// 重连间隔1秒 * 2^(重连次数)最大10秒
int retryDelay = Math.Min(1000 * (int)Math.Pow(2, _currentReconnectAttempt), 10000);
Log($"{retryDelay}ms后将尝试重新连接... (尝试 {_currentReconnectAttempt}次)");
Thread.Sleep(retryDelay);
continue; continue;
} }
} }
@@ -4734,23 +4794,12 @@ namespace JoyD.Windows.CS.Toprie
} }
}); });
// 等待连接完成或超时 // 移除主线程阻塞等待,让连接操作完全异步执行
if (!connectionCompleteEvent.WaitOne(_connectTimeout)) Console.WriteLine("设备连接请求已提交,将在后台执行,不阻塞主线程");
{
timeoutOccurred = true;
Console.WriteLine($"设备 {deviceId} 连接超时");
result = false;
_connectCancellationTokenSource.Cancel();
}
// 如果超时,记录超时信息 // 直接返回,不等待连接结果
if (timeoutOccurred)
{
UpdateConnectionStatus(ConnectionStatus.Disconnected,
$"设备 {deviceId} 连接超时({_connectTimeout}ms");
return; return;
} }
}
catch (Exception ex) catch (Exception ex)
{ {
Console.WriteLine($"连接设备异常: {ex.Message}"); Console.WriteLine($"连接设备异常: {ex.Message}");

View File

@@ -32,7 +32,7 @@ using System.Runtime.InteropServices;
// 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号 // 可以指定所有值,也可以使用以下所示的 "*" 预置版本号和修订号
//通过使用 "*",如下所示: //通过使用 "*",如下所示:
// [assembly: AssemblyVersion("1.0.*")] // [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.1")] [assembly: AssemblyVersion("1.0.0.3")]
[assembly: AssemblyFileVersion("1.0.0.4")] [assembly: AssemblyFileVersion("1.0.0.7")]
// NuGet包相关信息已在项目文件中配置 // NuGet包相关信息已在项目文件中配置

View File

@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
@@ -42,7 +42,7 @@
<DefineConstants>DEBUG;TRACE</DefineConstants> <DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
<DocumentationFile>$(AssemblyName).xml</DocumentationFile> <DocumentationFile>bin\Debug\JoyD.Windows.CS.Toprie.xml</DocumentationFile>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>