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).
Related
I'm developing software for logging data from RS232. There is a lot of data received each millisecond. Received data is stored in datagridview, you can see on attached picture.
For filling data I use dataGridView1.InvokeRequired from serialPort1_DataReceived event.
It works fine when there is just a few data on RS232. But when it receives many packets from RS232 GUI is working slow. There is no reaction for buttons pressing, and application consumes CPU. Once I disconnect RS232 physically there is no new data, buttons pressing response immediately.
My second approach was using dataGridView1.Rows.Add directly from serialPort1_DataReceived event. In this case it works fast, buttons are responsible. But dataGridView1 doesn't refresh, and some times flicker. I'm already using double buffering for it.
So my questions are:
How to speed up using InvokeRequired?
How to refresh dataGridView1 after filling dataGridView1.Rows.Add from serialPort1_DataReceived?
enter image description here
I developed a Windows Form application, using C#, that receives data through the serial port sent by a microcontroller. I'm receiving the data using the serialPort_DataReceived event in which I use ReadLine() to read the serial port. Then I use the Invoke method to call a function that will print the received string into a textBox. The problem is that the app can't keep up with the rate at which it receives the strings, for example, the string that I send from the microcontroller has the time at which it was sent and even though it has already passed 2 or 3 seconds the app is still printing the strings that were sent at the 0.2 second. And when I send a string to the microcontroller to stop sending data, the app onlys stops ptinting the data after a while, this is, it keeps printing the values stored in the receiving buffer.
I believe that is happens given the large amount of data that the app receives and the rate (I'm using a baud rate of 115200), one string for every millisecond. This is, I think that the app is always being interrupted by the DataReceived event and it doesn't has time to print the data and starts falling behind.
One way I though of overcome this problem was with multi-threading but I can't figure it out how. I already tried a few examples using the BackgroundWorker but I didn't manage to make it work at all. I'm still a noob in terms of programming Windows Form apps and even C#.
Can anyone confirm the cause of the problem? And how do I make a thread to print the received data?
You can utilize SerialPort.ReceivedBytesThreshold property and SerialPort.ReadExisting() method (or a StringBuilder instance) to update UI with a batch of strings at once rather than a single string.
For more information check:
Serial port DataReceived firing too much discussions on StackOverflow
Top 5 SerialPort Tips article by Kim Hamilton
Serial Port ReadLine vs ReadExisting or how to read the data from serial port properly discussion on StackOverflow
Quickest way to Update Multiline Textbox with Large Amount of Text discussion on StackOverflow
I'm creating a wpf application which reads sensor data from a webserver.
I then plot these data in graphs as I receive them. The data is sent several times a second.
My problem is that I have about 6 graphs I am plotting in the same window.
And it's lagging and updating unevenly, so I guess that is because they are all trying to update the same GUI thread at the same time.
How can I improve this? Can I have the graphs in different GUI threads in the same window, or is there another way to handle this?
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?
I have a Windows Form app written in C#. Its job is to send messages to a list of users. While those messages are being sent, I'd like to display status of the operation for each user. What I am doing (for each user) is creating a Label control and adding it to Panel. This works without a problem for a small set of users. When I increase the size to 1000 or more, the Visual Studio Debugger displays the following message:
A first chance exception of type 'System.ComponentModel.Win32Exception' occurred in
System.Windows.Forms.dll A first chance exception of type
'System.Reflection.TargetInvocationException' occurred in
mscorlib.dll
And then the application hangs. Any thoughts on what I'm doing wrong and how I can fix this?
Given the size, I would consider displaying your status in a RichTextBox.
What is happening is that you are generating too many handles and the Framework can't handle them all.
Use DataGridView instead
This is kind of a work around, but I don't think your users really want to look at a list of 1000 people. Show them the current/most recent and summary report for the rest. Or let them page through it.
Without seeing specific code, it is difficult to tell. If I were tasked with the same program, I would approach it differently.
I would use a Grid or a Listview to display the user and the status of his or her message being sent. These controls can handle an unlimited(well -- limited by system memory) number of rows. One row per user (or one row per message -- which ever works better).
That should be the only thing going on in the UI thread. Use a background worker (BacngroundWorker class), or a message queuing framework (MSMQ, SQL server) to have the messages sent asynchronously and report on the status back up through the BackgroundWorker.
As for your specific error -- I do not know why you are getting it. There should be no limit to the number of labels you can put on a WinForm. I suspect the error is caused by something else.
Put a ProgressBar on your form instead. If you're sending one message to 1000 people, just increment the ProgressBar by 1 each time you send a message.
If you're sending 5 messages to 1000 people, have one progress bar for messages and one for people (the second bar will cycle through its values once for each value on the first bar).
You can also have a label for each progress bar (saying "95% complete" or "Message 3 of 5" or whatever).
You can't have such a large number of controls on a .NET form, and even if you could, there's no way any user could look at them all at the same time anyway.
I like to use ListView in details mode. Usually, I'll make a routine for adding a row, make it selected, and call EnsureVisible() on the item to autoscroll to it.
Like already mentioned, controls correlate to one or more window handles and the OS can only hand out so many.
Too many controls! Make a single control to contain all those status messages. How about a multi-line textbox?
If you are literally only showing labels in the panel, I would suggest that you show the statuses using GDI. Write the text of the visible area in OnPaint and invalidate the area of a status label only when it changes.