dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
14.96k stars 4.65k forks source link

System.IO.SerialPort DataReceived drops bytes, not reliable. For serious RS232 use this library has been unusable. #106631

Open johngardner58work opened 1 month ago

johngardner58work commented 1 month ago

For sometime there have been many internet posts about problems with System.IO.Ports.SerialPort especially when reading higher speed data (e.g. 115200). We've had to resort to using interop and MSCOMM32.ocx or making DLLImport winapi kernel calls. Or using a 3rd party library (often written in C or C++) and also requiring DLLImport. These are not portable.

Transmit seems to work OK, but waiting for bytes on the receive side is flaky. We tend to use 115,200, n, 8, 1 with no handshaking. That works fine with MSCOMM32.ocx or Win32Api or C style software.

It is high time that this implementation is revisited and is made rock solid and performant. It needs to work well with both physical COM ports and also USB to Serial converters (e.g. with FTDI or Prolific chipsets). MSCOMM32.ocx works well with both.

Since some VCP and USB to serial devices are capable of going faster than 115200, MS should try to optimize throughput and latency. It would be nice if .NET Framework 4.8 and laterl .NET core implementations be fixed.

Serial ports are used extensively in the embedded world instead of direct USB. For this reason we need robust .net support.

Our device is a heart simulator, Commands (transmit) tend to be infrequent, while we send up Markers much more frequently. Mixed in there is that sent Commands get ACKs / Response (sometimes with payload), that's the only handshaking. Markers are asynchronous events related to the Heart beating in various chambers and if a pacemaker is attached pace detection events with some measurement payloads. As you can see this is more complex that many simple serial port needs. And it all works fine with mscomm32.ocx. We can distinquish between markers and ACKs. Each command gets an ID that must match the ACKs ID.

Thanks!

johngardner58work commented 1 month ago

I should say System.IO.Ports.SerialPort

Here is a snippet comment from Ben Voigt https://sparxeng.com/blog/software/must-use-net-system-io-ports-serialport: "The worst offending System.IO.Ports.SerialPort members, ones that not only should not be used but are signs of a deep code smell and the need to rearchitect all IOPSP usage:

The DataReceived event (100% redundant, also completely unreliable)
The BytesToRead property (completely unreliable)
The Read, ReadExisting, ReadLine methods (handle errors completely wrong, and are synchronous)
The PinChanged event (delivered out of order with respect to every interesting thing you might want to know about it)

"

dotnet-policy-service[bot] commented 3 weeks ago

Tagging subscribers to this area: @dotnet/area-system-io-ports See info in area-owners.md if you want to be subscribed.