【发布时间】:2011-02-22 06:57:27
【问题描述】:
由于串行端口通信是异步的,我很早就发现我的项目涉及与 RS 232 设备的通信,我必须有一个后台线程不断读取端口以接收数据。现在,我正在使用 IronPython (.NET 4.0),因此我可以访问 .NET 中内置的光滑 SerialPort 类。这让我可以编写这样的代码:
self.port = System.IO.Ports.SerialPort('COM1', 9600, System.IO.Ports.Parity.None, 8, System.IO.Ports.StopBits.One)
self.port.Open()
reading = self.port.ReadExisting() #grabs all bytes currently sitting in the input buffer
足够简单。但正如我提到的,我希望在新数据到达时不断检查该端口是否有新数据。理想情况下,只要有数据等待,我就会让操作系统告诉我。 Whaddaya 知道,我的祈祷得到了回应,有一个DataReceived 活动提供!
self.port.DataReceived += self.OnDataReceived
def OnDataReceived(self, sender, event):
reading = self.port.ReadExisting()
...
可惜,这毫无价值,because this event isn't guaranteed to be raised!
不保证每收到一个字节都会引发 DataReceived 事件。
那么回到编写侦听器线程。我使用BackgroundWorker 很快就完成了这项工作,它只是一遍又一遍地调用port.ReadExisting()。它在字节进入时读取它们,当它看到一行结尾(\r\n)时,它将读取的内容放入linebuffer。然后我程序的其他部分查看linebuffer,看看是否有完整的行等待使用。
现在,这显然是一个经典的生产者-消费者问题。生产者是BackgroundWorker,将完整的行放入linebuffer。消费者是一些代码,它尽可能快地使用来自linebuffer 的那些行。
但是,消费者有点低效。现在他一直在查看linebuffer,每次都发现它是空的;虽然偶尔会发现里面有一条线等着。优化这一点的最佳方法是什么,以便消费者只有在有可用线路时才醒来?这样消费者就不会不停地访问linebuffer,这可能会引入一些并发问题。
另外,如果有更简单/更好的方式从串行端口不断读取,我愿意接受建议!
【问题讨论】:
标签: .net python ironpython serial-port