【问题标题】:Two ways to implement an application invoving serial communication实现涉及串行通信的应用程序的两种方法
【发布时间】:2017-04-29 11:33:28
【问题描述】:

我正在编写一个应用程序,其中涉及与设备的串行通信等。 (在 C# 中)。我看过一些示例代码,具体有两个例子。

在第一个示例中,代码基于一个后台控件,该控件有一个 while 循环,用于检查是否有从串行端口(另一个控件)读取的数据以及何时进行一些处理

 private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{  serialPort1.Open();
 while (backgroundWorker1.CancellationPending == false)
     {        
       if (serialPort1.BytesToRead >= 240)
        {
         serialPort1.Read(RDATA, 0, 240);
         //Some other process

        }
     }
 serialPort1.Close();
}

第二个例子完全不同。这涉及委托和事件。在这种情况下,串行端口(在代码中创建)有一个事件“DataReceived”。为此,我们添加了一个事件处理程序

ComPort.DataReceived += 
              new System.IO.Ports.SerialDataReceivedEventHandler(port_DataReceived_1);

然后定义port_DataReceived_1函数,在其中读取输入数据

    private void port_DataReceived_1(object sender, SerialDataReceivedEventArgs e)
 {
   InputData = ComPort.ReadExisting();
   if (InputData != String.Empty)
      {
       this.BeginInvoke(new SetTextCallback(SetText), new object[] { InputData });
       }
 }

private void SetText(string text)
 {
   this.rtbIncoming.Text += text;
  }

无论如何,我可以在这里看到两种不同风格的编码串行通信。一方面,我们有一个持续的轮询(通过while),如果它不在另一个线程上,它将阻塞程序的其余部分。它是在不同的线程中完成的。 另一方面,我们有中断,其中仅在事件发生时才进行处理,而不是其余时间。不过,这一切都在主线程上完成。

我的问题是这些方法中的哪一种更可取。我想象第一种方法,即使它在不同的线程上,也会占用大量的计算机资源,甚至可能会将 CPU 的负载提升到 100% 或其他东西。 我更倾向于做第二个,但又是一个线程。 有什么建议和建议吗?

(我的应用程序不仅涉及串行通信,还可能涉及对接收到的数据进行处理,甚至可能涉及机器学习)

【问题讨论】:

  • 第一个 sn-p 相当糟糕,它烧毁了 100% 的核心,但这只是因为它是糟糕的代码,而不是因为该方法根本上是错误的。如果协议是复杂的,它会更方便。第三种选择是使用在 BaseStream 上等待 ReadAsync() 的异步代码。你必须自己决定。
  • 具体是什么东西使它成为糟糕的代码?
  • 它一遍又一遍地循环,等待 BytesToRead 变得足够大。燃烧100%核心,一事无成。没有意义,只需调用 Read()。他可能这样做是为了看到 CancellationPending 的变化。只需关闭端口,就会导致 Read() 失败。或者根本不打扰,端口通常应该在应用程序的生命周期内始终打开。那里有很多糟糕的 SerialPort 代码,请注意。

标签: c# multithreading events serial-port


【解决方案1】:

您绝对应该选择第二个选项,它可能由I/O Completion Port 线程处理。如果您正在编写 WinForms 应用程序,则需要确保检查 InvokeRequired 标志并通过将委托传递给 Invoke 方法在主线程上执行任何 UI 操作。

【讨论】:

  • 我明白了。所以第二个选项毕竟是在不同的线程中完成的,不是吗?我没看到。这就是为什么它使用 this.BeginInvoke 调用影响 UI 的 SetText 函数,其中 setTextCallback 是一个委托!
  • 是的,你明白了!仅供参考,通常您应该在BeginInvoke 处理程序中调用EndInvoke。在这种特殊情况下,只使用非异步调用可能是安全的。
猜你喜欢
  • 1970-01-01
  • 2019-03-16
  • 1970-01-01
  • 2013-09-30
  • 1970-01-01
  • 2017-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多