是什么导致 .NET SerialPort 类 DataReceived 事件触发?
我从 MSDN 文档中了解到,DataReceived 事件不一定每个字节都会触发一次。
但有谁知道导致事件触发的机制到底是什么?
每个字节的接收是否会重新启动一个计时器,该计时器必须在事件触发之前达到(例如字节之间 10 毫秒)?
我问这个问题是因为我正在尝试编写一个应用程序来读取来自串行端口的 XML 数据。
由于我的笔记本电脑没有串口,所以我使用虚拟串口模拟器。 (我知道,我知道——我对 ATM 机无能为力)。
当我通过模拟端口将数据传递到应用程序时,每个 XML 记录(大约 1500 字节)都会触发一次该事件。完美的。但是,当另一个办公室的同事尝试使用通过实际电缆连接的两台计算机时,每 10 个左右字节的 XML 后就会重复触发 DataReceived 事件,这使应用程序完全崩溃。
I understand from the MSDN docs that the event DataReceived will not necessarily fire once per byte.
But does anyone know what exactly is the mechanism that causes the event to fire?
Does the receipt of each byte restart a timer that has to reach, say 10 ms between bytes, before the event fires?
I ask because I'm trying to write an app that reads XML data coming in from a serial port.
Because my laptop has no serial ports, I use a virtual serial port emulator. (I know, I know--I can't do anything about it ATM).
When I pass data through the emulated port to my app, the event fires once for each XML record (about 1500 bytes). Perfect. But when a colleague at another office tries it with two computers connected by an actual cable, the DataReceived event fires repeatedly, after every 10 or so bytes of XML, which totally throws off the app.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
DataReceived 可以在一个或多个字节准备好读取时随时触发。它的确切触发时间取决于操作系统和驱动程序,并且在 .NET 中接收数据和触发事件之间也会有一个小的延迟。
您不应依赖 DataReceived 事件的时间来控制流。
相反,解析底层协议,如果您没有收到完整的消息,请等待更多消息。如果您收到多条消息,请确保不要解析第一条消息,因为它们将是下一条消息的开始。
DataReceived can fire at any time one or more bytes are ready to read. Exactly when it is fired depends on the OS and drivers, and also there will be a small delay between the data being received and the event being fired in .NET.
You shouldn't rely on the timing of DataReceived events for control flow.
Instead, parse the underlying protocol and if you haven't received a complete message, wait for more. If you receive more than one message, make sure to keep the left overs from parsing the first message because they will be the start of the next message.
正如 Mark Byers 指出的那样,这取决于操作系统和驱动程序。在最低级别,标准 RS232 芯片(对于我来说,我记不起每个人都复制来制作“标准”的那个芯片的名称)当其入站寄存器中有数据时将触发中断。驱动程序的“底端”必须获取该数据(可以是芯片缓冲区大小的任意数量),并将其存储在驱动程序的缓冲区中,并向操作系统发出它有数据的信号。此时,.NET 框架可以开始发现数据是否可用。根据操作系统向打开串行端口的应用程序发出信号的时间(这是操作系统级别的操作,并提供从 .NET 框架到操作系统/驱动程序级别实现的“真实”链接),实际上可能存在任意数量的数据>缓冲区中 1 个字节,因为驱动程序的底端可能同时加载更多数据。我敢打赌,在您的系统上,驱动程序提供了一个巨大的缓冲区,并且仅在数据流中出现明显暂停后才发出信号。另一方面,您同事的系统发出的信号要频繁得多。马克·拜尔(Mark Byer)关于解析协议的建议再次是正确的。我已经通过 TCP 套接字实现了类似的系统,处理这种情况的唯一方法是缓冲数据,直到获得完整的协议消息,然后将完整的消息交给应用程序。
As Mark Byers pointed out, this depends on the OS and drivers. At the lowest level, a standard RS232 chip (for the life of me, I can't remember the designation of the one that everyone copied to make the 'standard') will fire an interrupt when it has data in its inbound register. The 'bottom end' of the driver has to go get that data (which could be any amount up to the buffer size of the chip), and store it in the driver's buffer, and signal to the OS that it has data. It's at this point that the .NET framework can start finding out that the data is available. Depending on when the OS signals the application that opened the serial port (which is an OS level operation, and provides the 'real' link from the .NET framework to the OS/driver level implementation), there could literally be any amount of data > 1 byte in the buffer, because the driver's bottom end could've loaded up more data in the meantime. My bet is that on your system, the driver is providing a huge buffer, and only signalling after a significant pause in the data stream. Your colleague's system, on the other hand, signals far more frequently. Again, Mark Byer's advice to parse the protocol is spot on. I've implemented a similar system over TCP sockets, and the only way to handle the situation is to buffer the data until you've got a complete protocol message, then hand the full message over to the application.