Связь EasyModbus TCP замедляет работу приложения Windows
Приложение WinForms замедляется при увеличении количества методов внутри таймера для EasyModbus TCP. Что нужно сделать, чтобы увеличить скорость работы приложения?
Я подключаю подчиненное устройство из приложения WinForms с помощью Modbus TCP/IP. Библиотека 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 и отображает их в текстовом поле.
Работа всего приложения замедляется, когда количество методов для чтения и записи данных увеличивается, поскольку к данным из нескольких регистров необходимо обращаться одновременно.
Может ли кто-нибудь помочь мне с этой проблемой, как получить доступ к нескольким регистрам одновременно, не замедляя все приложение?
1 ответ
Ваше приложение не отвечает, потому что вы выполняете ввод-вывод в потоке диспетчеризации событий. Это блокирует его выполнение других задач, таких как рисование пользовательского интерфейса, реакция на события мыши...
Чтобы выполнить ввод-вывод в пуле потоков, вы можете использовать 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
уже предоставляет асинхронные методы, используйте их вместо них. В приведенном выше примере более или менее просто используется дополнительный поток для одновременной обработки ввода-вывода с вашим пользовательским интерфейсом.