.Net 中的低延迟串行通信
我一直在研究各种第三方库和 .Net 中低延迟串行通信的方法。我读了足够多的书,现在已经回到原点,由于各种相互冲突的观点,我所知道的和刚开始时一样少。
例如,框架中的功能被排除,因为一些令人信服的文章指出:“微软提供的解决方案在框架版本之间不稳定,并且缺乏功能。”
我发现文章抨击了许多旧的基于 COM 的库。我发现一些文章抨击了由于垃圾收集而导致整个 .Net 应用程序低延迟的想法。
我还读过一些文章,展示了如何为了低延迟通信的目的而调用 Windows API 功能是不可接受的。
这排除了我能想到的任何方法!
我真的很感谢那些经历过/经历过这种经历的人的一些话。理想情况下,我可以找到一个可靠的库/合作伙伴,而不必自己构建通信库。我有以下简单的目标:
- 持续低延迟串行 C# / VB.Net
- 32/64 位
- 中的通信有据可查(如果解决方案是第 3 方)
- 相对不受垃圾收集影响(通信和延迟方面)。
- 灵活(我不知道将来必须与什么接口!)我唯一确定的要求是我需要能够与许多不同的工业设备接口,例如基于 RS485 的线性执行器、串行/微控制器基于仪表和 ModBus(也是 RS485)设备。
非常感谢任何可能消除我的困惑的评论、想法、想法或文章链接!
I have been researching various third party libraries and approaches to low latency serial communications in .Net. I've read enough that I have now come full circle and know as little as I did when I started due to the variety of conflicting opinions.
For example, the functionality in the Framework was ruled out due to some convincing articles stating: "that the Microsoft provided solution has not been stable across framework versions and is lacking in functionality."
I have found articles bashing many of the older COM based libraries. I have found articles bashing the idea of a low latency .Net app as a whole due to garbage collection.
I have also read articles demonstrating how P/Invoking Windows API functionality for the purpose of low latency communication is unacceptable.
THIS RULES OUT JUST ABOUT ANY APPROACH I CAN THINK OF!
I would really appreciate some words from those with been there / done that experience. Ideally, I could locate a solid library / partner and not have to build the communications library myself. I have the following simple objectives:
- Sustained low latency serial
communication in C# / VB.Net - 32/64 bit
- Well documented (if the solution is 3rd party)
- Relatively unimpacted (communication and latency wise) by garbage collection .
- Flexible (I have no idea what I will have to interface with in the future!) The only requirement that I have for certain is that I need to be able to interface with many different industrial devices such as RS485 based linear actuators, serial / microcontroller based gauges, and ModBus (also RS485) devices.
Any comments, ideas, thoughts or links to articles that may iron out my confusion are much appreciated!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
.Net 串行端口类在高频发送接收小数据包时会消耗太多 CPU。它似乎也错过了一些事件。由于我需要能够每秒可靠地发送和接收 1000 次 16 字节数据包,因此我最终根据 Windows API 组合了一些东西,现在可以轻松地每秒发送 1000 个小数据包,同时几乎不消耗 CPU。我尝试了几乎所有可用的库,但在这个简单的任务中,它们都因 CPU 利用率过高或错过事件而失败。
The .Net Serial Port Class Consumes far too much CPU when sending receiving small packets at high frequencies. It also seems to miss some events. Since I needed to beable to send and receive 16 byte packets 1000 timesper seond reliably I wound up putting together something based off of the Windows API and can now easily fire 1000 small packets per second while consuming next to no CPU. I tried nearly every library available library, and fr this simple task, they all failed due to excessive CPU utilization or missed events.
在现代机器上,延迟不是问题。串行端口非常慢,19.2 kilobaud 简直就是小菜一碟,.NET SerialPort 类可以很好地处理它们。 DataReceived 事件由线程池线程异步传递,该线程使用 WaitCommEvent() 执行阻塞等待,您不能比这更快。
Latency is a non-issue on modern machines. Serial ports are glacially slow, 19.2 kilobaud is peanuts, the .NET SerialPort class handles them fine. The DataReceived event is delivered asynchronously by a threadpool thread that performs a blocking wait with WaitCommEvent(), you can't go faster than that.
我有一个 .NET 应用程序,在具有 16 个 COM 端口的服务器上运行,其中大约 11 个当前连接到各种设备,一些是 RS485,许多是 RS-232。 (此处的图表:http://blog.abodit.com/2010 /03/home-automation-block-diagram/)。这些设备中的大多数仅以 9600 波特率运行,并且大多数没有非常严格的时序要求。我每个设备都有一个处理接收的线程,当它以正常线程优先级运行时,所有其他非通信线程以较低优先级运行(无论如何,您都应该对大多数后台任务执行此操作)。我对这个设置没有任何问题。而且,顺便说一句,它还使用托管代码中的高优先级线程和 1 秒 DSound 缓冲区同时在三个声卡上播放音乐,所有这些都没有故障。
那么您的延迟要求有多严格、波特率是多少以及您想要提供多少个串行端口?在大多数正常波特率下,UART 上的缓冲区对于垃圾收集来说绰绰有余,并且对于延迟从其中取出下一个字节而言也绰绰有余。
GC 并不像人们想象的那么邪恶。在一个正确优先级的线程系统上,具有良好的对象大小和生命周期管理以及足够的缓冲(UARTS/声音缓冲区等),它可以表现得很好。 Microsoft 也在不断改进它,.NET Framework 4 现在提供后台垃圾收集。此功能取代了以前版本中的并发垃圾收集,并提供了更好的性能。请参阅 MSDN。
I have a .NET Application that runs on a server with 16 COM ports, about 11 of which are currently connected to various devices, some RS485, many RS-232. (Diagram here: http://blog.abodit.com/2010/03/home-automation-block-diagram/). Most of these devices are running just 9600 baud, and most don't have very tight timing requirements. I have a thread per device handling receiving and while it runs at normal thread priority, all other non-communication threads run at a lower priority (as you should do for most background tasks anyway). I have had no issues with this setup. And, BTW it also plays music on three sound cards at the same time using high-priority threads from managed code and 1second DSound buffers, all without glitching.
So how tight are your latency requirements, what baud rate and how many serial ports are you trying to serve? The buffer on your UART at most normal baud rates is more than sufficient for garbage collection and much more to delay taking the next byte off it.
GC is not as evil as it is made out to be. On a properly prioritized threaded system with good management of object sizes and lifetimes and sufficient buffering (UARTS/Sound buffers etc.) it can perform very well. Microsoft is also continuously improving it and the .NET Framework 4 now provides background garbage collection. This feature replaces concurrent garbage collection in previous versions and provides better performance. See MSDN.
对于您所描述的应用程序类型来说,.NET 通常不是一个好的选择。这种事情至少需要低延迟的部分需要本机代码和 C++ 等语言。
.NET is generally a poor choice for the kind of application you describe. This kind of thing is going to require native code and a language like C++ for at least the portion that requires low-latency.
就我个人而言,我喜欢我的 BBUSB 接口。当切换到 Bitbang 模式时,它允许您直接开/关控制 8 个引脚,您可以将其设置为输入或输出。
“但我需要一个串口。”你说。这是完全有可能的。只需将引脚连接到 9 针公串行端口即可。
Personally I love my BBUSB interface. When switched to bitbang mode it allows you direct on/off control 8 pins which you can set to be input or output.
"But I need a serial port." You say. It's entirely possible. Simply wire up the pins to a 9 pin male serial port and you're good to go.