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



我正在使用NModbus4通过ModbusRTU(RS485(进行通信。我的程序需要不断从设备获取数据,该设备断开连接并且经常连接。当设备断开连接时,我在女巫期间遇到超时异常(可以理解(,程序滞后(通过表单、按下按钮等(,因为它需要等待设备响应。

是否可以将 Modbus 连接移动到单独的线程以与用户界面并行处理它(或者是否有更好的选择(?

如果是这样,请帮助我一个简单的示例,如何与事件相关联(我正在通过事件传递设备数据和信息以显示数据(。

示例代码:

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
}

这段代码的问题在于我无法将事件从新线程传递到当前线程(另外我不知道线程的方法是否正确(。

我只是从 C# 和 .NET 开始,所以示例代码可能不符合标准约定 - 很抱歉。

线程是一个太低级的原语 - 我建议调查任务并尽可能避免使用线程。

这是代码在您的情况下的样子。 DataManagement.RequestData 调用发生在不同的线程上,取自线程池,但紧接着您再次进入主线程的上下文,因此您不必执行任何同步/封送处理/等。 如果 ProcessData 方法也很慢,那么您可以执行与 DataManagement.RequestData 相同的操作 - 对任务执行它。同样,不需要同步。

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) { }
}

最新更新