在Quartz.Net的IJob实现类中调用EasyModbus出现连接错误如何解决?
问题原因
- 未主动调用连接方法:你在
IJob的Execute方法中直接调用ReadHoldingRegisters读取数据,但全程没有调用你写的ModbusConnect方法建立Modbus TCP连接,modbus实例一直处于未连接状态,因此报连接错误。主窗体逻辑中你应该是提前手动调用了连接方法,所以可以正常运行。 - Quartz作业实例的生命周期问题:Quartz默认每次触发作业时都会创建一个新的
Gorev类实例,你将ModbusClient作为实例字段,每次作业触发得到的都是全新的未初始化连接的客户端对象,无法复用之前的连接状态。 - 连接方法逻辑错误:你写的
ModbusConnect方法逻辑存在问题:如果当前客户端已经处于连接状态,方法会主动断开连接并返回断开后的状态,不符合连接方法的预期功能。
解决方法
推荐采用「每次作业执行时新建连接、读取完成后主动释放连接」的方案,避免长连接因为网络波动断开、多线程并发冲突等问题,修正后的代码示例如下:
public class Gorev : IJob { private const string Address = "10.100.135.20"; private const int Port = 502; public Task Execute(IJobExecutionContext context) { // 每次执行作业时新建Modbus客户端 var modbus = new ModbusClient(Address, Port); try { // 主动建立连接 modbus.Connect(); if (modbus.Connected) { int[] frekans = modbus.ReadHoldingRegisters(0x009E, 1); // 此处添加你处理frekans数据的逻辑 } } catch (Exception ex) { // 此处添加异常日志记录逻辑,方便排查问题 Console.WriteLine($"Modbus读取失败:{ex.Message}"); } finally { // 主动断开连接释放资源 if (modbus.Connected) { modbus.Disconnect(); } } return Task.CompletedTask; } }
如果你的作业执行频率很高,需要复用连接减少连接开销,可以将ModbusClient注册为单例模式,确保全局只有一个客户端实例,每次执行作业前先判断连接状态,断开的话再重连即可,同时要注意加锁避免多线程并发操作客户端。
内容的提问来源于stack exchange,提问作者kaptan
相关产品推荐
相关产品推荐

