简体   繁体   English

使用线程进行外部通信(PC-> RS485设备)

[英]Using threads for external communication (PC -> RS485 device)

I'm using NModbus4 to communicate over ModbusRTU (RS485). 我正在使用NModbus4通过ModbusRTU(RS485)进行通信。 My program needs to continuously get data from a device, that device is disconnected and connected very often. 我的程序需要不断地从设备获取数据,该设备经常断开连接。 While the device is disconnected I'm getting timeout exception (understandably) during witch the program is laggy (going through forms, pressing buttons etc.) since it waits sometime for the device to response. 当设备断开连接时,我在等待期间收到超时异常(这是可以理解的),因为程序等待设备响应,因此程序运行缓慢(正在浏览表格,按下按钮等)。

Is it possible to move the Modbus connection to a separate thread to handle it parallel to user interface(or is there a better option)? 是否可以将Modbus连接移动到单独的线程以与用户界面并行处理(或者有更好的选择)?

If so please help me with a simple example how to do it in connection with events (I'm passing device data and information through an event to display data). 如果是这样,请帮我举一个简单的示例,说明如何与事件相关联(我正在通过事件传递设备数据和信息以显示数据)。

Sample code: 样例代码:

    public MainGui()
    {
        InitializeComponent();
        DataTransport DataManagment = new DataTransport(); //DataTransport is a class that handles communication and publishes event 'DataSent'
        DataManagment.DataSent += new EventHandler<DataSentArgs>(UnpackData);
    }

    private void slaveDataReqTimer_Tick(object sender, EventArgs e)
    {
        //Timer that is responsible for fetching data
        new Thread(() =>
        {
            Thread.CurrentThread.IsBackground = true;
            DataManagment.RequestData();

        }).Start();
    }

    public void UnpackData(object sender, DataSentArgs e)
    {
        //Doing some stuff when data arrives
    }

The problem with this code is that I can't pass the event from new Thread to current Thread (additionally I don't know if the approach with threads is correct). 这段代码的问题是我无法将事件从新线程传递到当前线程(此外,我不知道使用线程的方法是否正确)。

I'm just starting with C# and .NET so the sample code might not be in accordance with standard conventions - sorry for that. 我只是从C#和.NET开始,所以示例代码可能与标准约定不符-抱歉。

Threads is a too low-level primitive for this - I would recommend to investigate tasks and avoid using threads in general as much as possible. 为此,线程是一个太低级的原语-我建议研究任务,并尽可能避免一般地使用线程。

This is the code how it would look like in your case. 这是您情况下的代码。 The DataManagement.RequestData call happens on a different thread, taken from the thread pool, but right after that you get into the context of your primary thread again so you'll not have to perform any synchronization/marshaling/etc. DataManagement.RequestData调用发生在不同的线程上,该线程取自线程池,但是此后立即进入主线程的上下文,因此您不必执行任何同步/封送处理等。 If the ProcessData method is also slow, then you can do the same as with DataManagement.RequestData - perform it on a task. 如果ProcessData方法也很慢,则可以执行与DataManagement.RequestData相同的操作-在任务上执行它。 And again, no synchonization will be needed. 再一次,将不需要同步化。

public MainWindow()
{
    InitializeComponent();

    var cts = new CancellationTokenSource();
    Unloaded += delegate { cts.Cancel(); };
    ProcessData(cts.Token);
}

async void ProcessData(CancellationToken ct)
{
    try
    {
        while (true)
        {
            ct.ThrowIfCancellationRequested();

            try
            {
                var dataItem = await Task.Run(() => DataManagement.RequestData());

                ProcessData(dataItem);
            }
            catch(Exception_Thrown_By_RequestData e)
            {
                // decide what do - either break the loop or continue if
                // this is not a heavy faiulre
            }

            await Task.Delay(DelayTime, ct);
        }
    }
    catch (TaskCanceledException) { }
    catch (OperationCanceledException) { }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM