3.NModbus4 长距离多设备超时 C# + WPF 完整示例

cs 复制代码
/// <summary>
/// 当前是否已建立 Modbus-TCP 连接(只读,由 Connect/Disconnect 维护)
/// </summary>
public bool IsConnected;

/// <summary>
/// 建立 Modbus-TCP 连接
/// 调用前请先设置 <see cref="IpAddress"/> 与 <see cref="ServerPort"/>
/// </summary>
/// <returns>true 成功;false 失败(异常已内部记录)</returns>
public bool Connect()
{
    // 100 ms 取消令牌 → 避免半开连接长时间阻塞 UI
    using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(0.1));

    try
    {
        // 1. 创建 TcpClient 并禁用 Nagle,降低小包延迟
        _tcpClient = new TcpClient
        {
            SendTimeout    = 100,   // 发送超时 100 ms
            ReceiveTimeout = 100,   // 接收超时 100 ms
            NoDelay        = true   // 立即发送,不等待合并
        };

        // 2. 异步连接,最多等待 5 秒(与令牌叠加)
        var connectTask = _tcpClient.ConnectAsync(IpAddress, ServerPort);
        connectTask.Wait(cts.Token);        // 先受 100 ms 令牌限制
        connectTask.GetAwaiter().GetResult(); // 再抛异常

        // 3. 连接成功 → 创建 NModbus 主站实例
        IsConnected   = _tcpClient.Connected;
        _modbusMaster = ModbusIpMaster.CreateIp(_tcpClient);

        return true;
    }
    catch (Exception ex)
    {
        // 记录失败状态与日志
        IsConnected = false;
        Debug.WriteLine($"Connection error: {ex.Message}");
        return false;
    }
}

如果你刚接触 Modbus-TCP,建议先回看《12.NModbus4在C#上的部署与使用 C#例子 WPF例子》等往期文章------那里已经演示了如何引用 NModbus4、创建 TcpClient、构建 ModbusIpMaster 并读取第一个寄存器。本文默认你已能完成"建连接 → 读寄存器"这一最小闭环,下面直接切入"连接阶段最容易被忽视、却又最影响实时性"的环节:超时。

示例代码把"建连"做成 Connect() 方法,内部用 ConnectAsync(IpAddress, ServerPort) 异步发起 TCP 三次握手,同时给 CancellationTokenSource 设定 100 ms 取消令牌;这意味着:

  • 网络瞬间可达时,连接在几十毫秒内完成,令牌不会触发,流程无感通过;

  • 一旦出现半开连接、IP 不可达或端口未监听,最多只阻塞 100 ms 就会被强制取消,避免 UI 卡死。

    此外,代码把 TcpClient.NoDelay = true 放在连接前,确保小包立即发出,减少第一个 Modbus 请求的延迟

当你要轮询 80 台设备时,如果每台都"等 1-2 秒才报连接失败",总启动时间 = 80 × 2 s = 160 s ,界面直接假死。把连接超时压到 100 ms 后,80 台总探测时间 < 8 s (并行甚至 < 0.2 s),失败设备可立即标记离线并继续 ,既保证启动速度,也让后续轮询线程快速进入"只与在线设备通信"的状态,实时性与用户体验同时提升

相关推荐
雨落倾城夏未凉6 天前
第四章c#方法-参数数组和可选参数(16)
后端·c#
唐青枫7 天前
线程不是越多越快:C#.NET Thread 生命周期、同步与后台工作线程实战
c#·.net
唐青枫8 天前
别只会反射:C#.NET Emit 动态生成代码实战详解
c#·.net
Caco_D8 天前
一行代码抓遍全网 20 个热榜!Aneiang.Pa 4.0 发布 — 极简 .NET 爬虫库
爬虫·.net
咕白m6258 天前
.NET 环境下 Word 超链接批量提取方案
c#·.net
用户91721561902118 天前
C# 通信协议增量解析:用状态机处理半包和粘包
c#
小码编匠8 天前
C# 工控上位机必备:数据转换工具类与十个核心模块
后端·c#·.net
唐青枫10 天前
别再乱用 StartNew:C#.NET TaskFactory 任务调度实战详解
c#·.net