【发布时间】: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