here are my suggestions:
use a single BackGroundWorker per COM port; use its progress reporting facility to report displayable results.
Use synchronous read operations, thus avoiding the tricky DataReceived event.
If you are lucky and the peripheral reports text messages ending on some specific terminator, use ReadLine(); when necessary, adjust the NewLine property to equal that terminator. If not, just use Read and have the BGW discover the beginning and end of every message.
For the UI use the simplest List oriented Control that satisfies your interactive requirements; a ListView is good, however I prefer a ListBox.
Define a little class holding the raw data of one displayable result. That is one object, no more expensive than the array a ListView would need. Instances of this class, not strings, are to be added to the ListBox Items collection.
Make the ListBox ownerdrawn, giving it a fixed ItemHeight, and an appropriate DrawItem handler that takes care of horizontal positioning, coloring, and whatever fancy styling you may want.
That's it; and it is bound to be simpler than the code you probably are experementing with right now...
Luc Pattyn [My Articles]
If you can't find it on YouTube try TikTok...