c# - EasyModbus TCP 通信减慢 Windows 应用程序
问题描述
当 EasyModbus TCP 计时器内的方法数量增加时,WinForms 应用程序会变慢。应该怎么做才能提高应用程序的速度?
我正在使用 Modbus TCP/IP 从 WinForms 应用程序连接从设备。EasyModbus TCP/IP 库用于建立 WinForms 应用程序和从设备之间的通信,数据(浮点数)应该不断地从客户端读取和写入,因此方法被写入一个用于 Modbus 通信的计时器中。当方法的数量增加时,整个应用程序就会变慢。
using EasyModbus;
ModbusClient modbusClient;
tmr_Modbus_Com.Enabled = false;
timer1.Enabled = false;
private void tmr_Modbus_Com_Tick(object sender, EventArgs e)
{
tmr_Modbus_Com.Enabled = false;
modbusClient.WriteMultipleRegisters(2, ModbusClient.ConvertFloatToRegisters((float)variable, ModbusClient.RegisterOrder.HighLow)); //writing float data in "variable" to client register 40001 and 40002
textbox1.Text = ModbusClient.ConvertRegistersToFloat(modbusClient.ReadHoldingRegisters(394, 2), ModbusClient.RegisterOrder.HighLow).ToString(); //reading data from two registers 393 and 394 and displays on a textbox, "textbox1"
tmr_Modbus_Com.Enabled = true
}
上面的代码返回预期的结果,它从 WinForms 写入浮点数据到寄存器号 40001,它从客户端 ModBus 寄存器 40395 读取数据并显示在文本框中。
当读取和写入数据的方法数量增加时,整个应用程序会变慢,因为需要同时访问来自多个寄存器的数据。
谁能帮我解决这个问题,如何一次访问多个寄存器而不减慢整个应用程序的速度?
解决方案
您的应用程序没有响应,因为您正在事件调度线程上执行 I/O。这会阻止它执行其他任务,例如绘制 UI、对鼠标事件做出反应......
要在线程池上执行 I/O,您可以像这样使用 async/await(未经测试!)
// 1. Run the Write - Part on a Threadpool Thread ...
private Task WriteRegAsync( float variable , ModbusClient client )
{
return Task.Run(() => {
client.WriteMultipleRegisters(
2,
ModbusClient.ConvertFloatToRegisters( variable,
ModbusClient.RegisterOrder.HighLow)
);
});
}
// 2. Run the Read-Part on a Threadpool Thread
private Task<string> ReadRegAsync( int address, ModbusClient client )
{
return Task.Run( () => {
return ModbusClient.ConvertRegistersToFloat(
client.ReadHoldingRegisters(address, 2),
ModbusClient.RegisterOrder.HighLow)
.ToString();
});
}
// "async" makes "await" available for use. Since this is an EventHandler, "async void" is ok. (Usually, you make that "async Task")
private async void tmr_Modbus_Com_Tick(object sender, EventArgs e)
{
tmr_Modbus_Com.Enabled = false;
// Write _asynchronously_, your app will stay responsive.
await WriteRegAsync( (float)variable, modbusClient );
// then read asynchronously. Again, App will stay responsive.
textbox1.Text = await ReadRegAsync(384, modbusClient);
tmr_Modbus_Com.Enabled = true
}
请注意,这不是生产就绪代码!对事件处理程序的相邻调用可能会相互“超越”。您可能想要添加一些错误处理、日志记录...
还有一点:如果ModbusClient
已经提供了异步方法,那么就使用它们。上面的例子或多或少只是使用一个额外的线程来同时处理你的 UI 内容的 I/O。
推荐阅读
- python - python:如何使 simple-salesforce 的批量插入插入有效记录并捕获无效记录?
- android - 我是 Android 开发的新手,当我想为我的 xml 文件添加颜色时,比如@color/white,我被告知“无法解析符号 @color/white”
- mariadb - MariaDB Spider 与 Galera Clusters 故障转移解决方案
- grails - Grails 4:如何禁用域对象的深度验证以进行测试
- r - 一个代码块中有多个小标题。在 r markdown 中编织后如何显示它们?每次我只显示最后一个小标题
- javascript - 如何从到一个特定的表格里面?
- c++ - 为什么指针对象不会被自己删除,因为其他对象在 C++ 程序结束时被删除?
- python - 如何在 python numpy 的二维数组中将位置(第 2、第 3 或第 4 等)转换为索引(第 1 位置为 00,第 2 为 01 等)?
- git-clone - 克隆图中的“克隆”是主还是起源?
- java - 测试时没有可用于 direct-vm 类型路由的骆驼消费者