This commit is contained in:
xyy
2026-04-10 18:54:06 +08:00
parent 61c5e9f006
commit db683ead3b
4 changed files with 54 additions and 9 deletions

View File

@@ -3,6 +3,8 @@ using System;
using System.Net;
using System.Net.Sockets;
using System.Threading.Tasks;
using System.Threading;
using System.Threading.Tasks;
namespace MembranePoreTester.Communication
{
@@ -17,15 +19,31 @@ namespace MembranePoreTester.Communication
_config = config;
}
private async Task EnsureConnectedAsync()
public async Task EnsureConnectedAsync(int retryCount = 3)
{
if (_tcpClient != null && _tcpClient.Connected)
return;
for (int i = 0; i < retryCount; i++)
{
if (_tcpClient == null || !_tcpClient.Connected)
try
{
_tcpClient?.Close();
_tcpClient = new TcpClient();
await _tcpClient.ConnectAsync(_config.IpAddress, _config.Port);
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(3));
// 现在可以直接使用扩展方法
await _tcpClient.ConnectAsync(_config.IpAddress, _config.Port).WithCancellation(cts.Token);
_master = ModbusIpMaster.CreateIp(_tcpClient);
return;
}
catch (Exception ex) when (i < retryCount - 1)
{
System.Diagnostics.Debug.WriteLine($"连接失败,{500}ms 后重试... {ex.Message}");
await Task.Delay(500);
}
}
throw new Exception($"无法连接到 PLC ({_config.IpAddress}:{_config.Port}),请检查网络和 PLC 状态。");
}
// 读取两个连续的保持寄存器转换为32位浮点数假设大端模式
public async Task<float> ReadFloatAsync(ushort startAddress)
@@ -85,11 +103,12 @@ namespace MembranePoreTester.Communication
return result[0];
}
public bool IsConnected => _tcpClient != null && _tcpClient.Connected;
public async Task<ushort[]> ReadHoldingRegistersAsync(ushort startAddress, ushort count)
{
await EnsureConnectedAsync();
await Task.Delay(100);
// await Task.Delay(100);
return await _master.ReadHoldingRegistersAsync(_config.SlaveId, startAddress, count);
}
@@ -176,6 +195,22 @@ namespace MembranePoreTester.Communication
{
_master?.Dispose();
_tcpClient?.Close();
_tcpClient?.Dispose();
}
}
public static class TaskExtensions
{
public static async Task WithCancellation(this Task task, CancellationToken cancellationToken)
{
var tcs = new TaskCompletionSource<bool>();
using (cancellationToken.Register(s => ((TaskCompletionSource<bool>)s).TrySetResult(true), tcs))
{
if (task != await Task.WhenAny(task, tcs.Task))
throw new OperationCanceledException(cancellationToken);
}
await task;
}
}
}