I am writing an application that will display serial/USB data at a rate of up to 250kb/sec. I am using the .net SerialPort class and reacting to the DataReceived event. For early implementations of this software, I simply stored the incoming data in a WinForms RichTextBox. This solution works fine until there are 50k - 100k lines in the control, at which point the application bogs down. Since then, I've tried accomplishing my goals with WPF and found the same problem. I tried, at one point, to keep only the currently visible text in the textbox, and store the rest in a large List<string> but this solution required a huge number of workarounds and, in the end, was abandoned - I'd rather not reinvent the wheel.
Now I come to you for a thread of hope - I am willing to try anything! Should I use a custom control (both pay and free controls are welcome)? SQLite? Virtualization as described above? Should I try polling the SerialPort instead of reacting to events?
Use a thread to read the data and write it directly to a file. Have your app refresh the last x number of lines from the file every so often. Maybe even have the refresh based off of a notification from the reader thread?
By using multiple threads you'll keep the UI responsive and by writing straight to a file you'll ensure you've collected all of the data. Also, it will allow you to pause the display long enough to actually copy/paste the data you want while continuing to capture data.
Possibly you could implement your own type of file reader that would allow the user to "scroll" through the file by only loading the parts you can actually display on screen at one time.
If the data is largely line oriented (ReadLine) then put it in a ListBox. It is the fastest control for putting lots of text onscreen.
But you will find that all UI controls are geared toward human interaction, not to the speed of a Port. Best thing to do would be to rethink your design. What is that data for anyway?
Related
I'm new to C# and WinForms, and i'm developing an application, which would allow me to read data from serial port and display it on some display tool (listview,...).
Now, i got serial communication and other functionalities working, but i'm having a problem with displaying the data. I need to be able to display incoming data really fast (every 1ms). To display data (for now), i'm using dataGridView, but the problem is that dataGridView is not fast enough.
So my question is: Is there some way to display data that fast? I know the human eye can't really see data in this interval, but still... It would be prefered to display data in dataGridView-like display, since it's really easy to organize data.
Best regards,
Nejc
You are not going to succeed displaying data every 1 ms. What you should do is buffer the incoming data on one thread, then every N incoming data, call on a method to display the data (i.e. you will be adding N rows at a time). Note you will need to use Invoke() as you will be calling on the GUI from a different thread (the thread that receives the data, not the thread that created the GUI).
Here is my problem for the winform rich textbox, a program receive message from car parking hardware by TCP/IP and I display the Events in the winform richtextbox by
richtextbox.AppendText()
everything are working well except the program freeze within a day or two
Is there a better way to hand this?
Write to log file and bind it to the rich textbox?
This has been asked before.
Things to consider: Memory limits, HD (file size) and RAM (display)
If you want to implement this with WinForms and not use some existing logging code I think a ListView and a random access file of a fixed size with datetime and limited log string as a ring buffer would do. Or use e.g. SQLite (delete entries older than today - TimeSpan, insert new) and use a DataGridView (ideally derived and double buffered for smooth scrolling)..
Recently, I have been trying to get the built-in Windows 7 narrator/screen reader to be compatible with my WPF app. There is very little info about this, but what I have read is that I can set an attached property (AutomationProperties.HelpText, AutomationProperties.AutomationID).
The problem I am having is that the UI contains a progress bar and the current progress value is periodically read out by the screen reader as it changes. In this case, reading out the progress is not desirable but I cannot find a way to turn this off. I thought maybe I could set this by accessing the AutomationPeer associated with the element, but this doesn't seem to be the case (I can force an event to be raised, but I cannot have it ignore an event).
Does anyone know of a way to do this?
This is something that's typically controlled by the screenreader itself, via user settings/options, not something you can do at the application level. Narrator, which comes with Windows, is a fairly basic screenreader; think of it more like a notepad or wordpad level compared to a screenreader like Jaws or NVDA, which are more like Word. Narrator has minimal options, while the other two likely have all sorts of options that the user can use to customize when the screenreader speaks out specific events.
So, long story short; there's nothing you can do here. Ensure that the events are sent, that way a screenreader can chose to read them or not read them, as the user directs.
Also, keep in mind that Narrator is a basic screenreader, most users will actually be using something like Jaws (which costs $800 or so) or NVDA (free!), so consider testing with those to get a closer feel for what a real-world screenreader user would experience.
I need to display a "busy" indicator in a form while executing a long
running single command (ReadXML or WriteXML). So far, I'm using
Cursor.Current = Cursors.WaitCursor;
but I'm looking for a more adqeuate way to do it. There's no need
to display the percent done, only a visual reference that the program is
working (like a ProgressBar marquee style -not available for .NET CF-).
I'm using C# / WinForms / .NET CF 2.0
TIA
Showing progress is often desirable. But you do need to be able to measure progress to make that meaningful. Guessing that you meant DataSet.ReadXml(), that class doesn't have any kind of ProgressChanged event that you could use to let the user know how far the job got along. Nor can you guess up front how long it is going to take. Execution time is roughly proportional to the size of the .xml file but the exact proportion is impossible to guess accurately.
All you can do is let the user know "I'm busy, don't expect anything for a while". The hourglass cursor has been the standard way of doing so for the past 20 years. You can get fancier with an animation. Which is all that a ProgressBar in marquee mode really is. It doesn't help the user at all. Albeit that it has a slight bit of information added: "the operating system hasn't crashed". Useful 20 years ago.
You can create your own animation. Do animated GIFs work on CF? If not, you can flip bitmaps yourself. You do however take on an additional burden, you have to keep the animation animating. That requires that you run the ReadXml() call on another thread so that the UI thread is available to keep the image updated. No BackgroundWorker in CF, you'll have to spin that thread up yourself.
I'm looking for a way to embed a cmd "Shell" into a Form. I want to build a C# based application that acts as a Terminal, better than the Powershell window (no tabs) or cmd (no nothing). Just start these interpreters in the backend.
I guess MS never thought of doing this. Any ideas what From elements I could use?
Thanks,
i/o
That's not a trivial task you're undertaking. I know of one project (Console2) which basically polls the screen buffer of the underlying console window and displays in its own. You certainly will have trouble coping with interactive applications like Far and the like as they (a) rely on getting keyboard events and (b) on manipulating their screen buffer. Both are icky things if you want a suitable wrapper around the console window functionality. Mouse input is possible as well (unless Quick Edit mode is enabled) which could give you further headaches.
I doubt you can use a ready-made control for this. Basically you need to display a grid of cells each of which has a foreground and background color. You could probably use a RichTextBox for this but I'd guess it's far from ideal.
Also I don't think no one at MS ever thought of this. It's just that there's a limited budget for new features and every one of them needs to be specified, implemented, tested, tested more for regressions with millions of applications out there, etc. It's just a freaking expensive thing (if you don't want to misuse your customers as testers, which they aren't).
It would propably be the easiest to extend the Textbox class and add logic so that it behaves like a console (respond to the KeyPressed/KeyUp/KeyDown events or similar). You can also add events for those things that your console needs to respond to. For example, add a CommandEntered event.
Basing your new console on a TextBox gives you the editing and display features of the textbox "for free", so you do not need to re-implement that.
You could use a richtext box, and set the background to black and foreground to white. RTB instead of text box to handle larger amounts of data.
You would have to write an awful lot of code to simulate the terminal though.