从串行com端口读取的增量延迟

时间:2019-04-02 20:25:28

标签: c# wpf serial-port

我正在构建同时读取两个串行端口的WPF应用程序。一个端口(称重机)上的设备每秒发送7个字符串。第二个端口(牛奶分析仪)上的设备通过在机器上手动按下按钮来发送275个字符串。

我正在使用以下代码在启动时配置和打开端口:

//serial port for Milk Machine
serialPortMilk = new SerialPort
            {
                PortName = EnVar.GlobalSetting.MilkMachinePort,
                BaudRate = EnVar.GlobalSetting.MilkMachineBaudRate,
                Handshake = Handshake.None,
                Parity = Parity.None,
                DataBits = EnVar.GlobalSetting.MilkMachineDataBits,
                StopBits = StopBits.One,
                ReadTimeout = 1000,
        };

        serialPortMilk.DataReceived += new SerialDataReceivedEventHandler(RecieveMilk);
        serialPortMilk.Open();


//serial port for Weighing Machine
 serialPortWeight = new SerialPort
 {
              PortName = EnVar.GlobalSetting.WeightMachinePort,
                    BaudRate = EnVar.GlobalSetting.WeightMachineBaudRate,
                    Handshake = Handshake.None,
                    Parity = Parity.None,
                    DataBits = EnVar.GlobalSetting.WeightMachineDataBits,
                    StopBits = StopBits.One,
                    ReadTimeout = 300,
                    WriteTimeout = 500,
                };

                serialPortWeight.DataReceived += new SerialDataReceivedEventHandler(ReceiveWeight);
                serialPortWeight.Open();

我能够连续读取称重机,并且每秒在应用程序UI中正确更新该值。

我面临的问题是: 当用户按下挤奶机上的按钮并在端口上发送数据时,要花费4到5秒钟,直到触发DataReceived事件。如果我连续进行操作,即再次按计算机上的按钮,则下一个DataReceive事件将在8-10秒后触发。这种延迟不断增加。另一个事实是,如果我关闭了Weighing Machine端口,而只是保持Milk Machine端口保持打开状态,则立即触发Milk Machine端口的DataReceived事件。

这是我在ReceiveMilk代表内部所做的事情:

try
{
  machineData = serialPortMilk.ReadLine();
  serialPortMilk.DiscardInBuffer();
}
catch (Exception ex)
{
  return;
}

//string operations

Dispatcher.Invoke(new Action(() =>
{
  //set values in UI
}}));

和ReceiveWeight委托中的差不多。

我尝试了不同的超时,读取缓冲区,读取之前/之后的线程休眠..但是没有任何方法可以解决此问题。

2 个答案:

答案 0 :(得分:0)

当涉及到多个 DataReceived时,这是我在使用SerialPort事件时遇到的常见问题。如果您通过Google搜索该问题,就会发现它是一个与时间一样古老的问题。

Refer to this MSDN thread。引用其中一个响应:“。NET SerialPort不是一个很好的组件” 。有人报告说,通过调整ReceivedBytesThreshold值可以取得成功。大多数人不得不诉诸于数据轮询,而不是基于事件的方法(also here)。

首先尝试使用阈值,因为对您来说这可能是一个快速的胜利。否则,可能需要重构。

答案 1 :(得分:0)

我有同时在30个串行端口上最多运行30台设备的软件,并且DataReceivedEvent滞后没有任何问题。我认为问题可能在于您使用的machineData = serialPortMilk.ReadLine();中,我认为ReadLine是一个阻止函数。这可能导致线程挂断。我建议使用ReadExisting(),因为它会立即返回Serial Port类的字符缓冲区中的内容。

编辑:

根据MSDN:

  

默认情况下,ReadLine方法将阻塞,直到收到一行为止。如果不希望出现这种情况,请将ReadTimeout属性设置为任何非零值,以强制ReadLine方法在端口上没有行的情况下引发TimeoutException。

在此处详细了解ReadLine属性:https://docs.microsoft.com/en-us/dotnet/api/system.io.ports.serialport.readline?view=netframework-4.7.2