Связь 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уже предоставляет асинхронные методы, используйте их вместо них. В приведенном выше примере более или менее просто используется дополнительный поток для одновременной обработки ввода-вывода с вашим пользовательским интерфейсом.

Другие вопросы по тегам