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
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).
I have a relatively short C# program that feeds data over an RS232 port using the following format:
'STX' Header 'Checksum' 'ETX'
'STX' data1 'Checksum' 'ETX'
'STX' ... 'Checksum' 'ETX'
'STX' dataN 'Checksum' 'ETB'
The receiving end is supposed to reply with either an ACK or NAK byte upon receiving the ETX/ETB.
This works fine running on computers with Windows 7 64 bit.
However there was a problem getting the program to start on a Win XP 32 machine, because I had built the program to target .NET version 4.5 (which apparently isn't supported by that version of Win XP).
I changed it to target .NET version 4 instead and now the program starts just fine. But the receiving end doesn't respond with ACK or NAKs anymore, only the first time (upon sending the datafile header).
I printed out the byte buffer on the console and at the place where the ETX byte is supposed to be there is an UP DOWN ARROW WITH BASE symbol (↨) which tells me it somehow didn't send an ETX at all.
What's weird about this is that it works fine on windows 7 machines, and the first transmission (header) returns an ACK just like it's supposed to, but when the first data packet is sent no more replies... no ACK or NAK.
In case anyone run into similar problems; my problem was that I used a USB to serial converter. It caused the timings to become all messed up. What I did to solve it was to subscribe to the SerialPort's DataReceived Event, and then grab the data inside the event handler with serialport.ReadExisting() (which also clears the receive buffer). So the thread would roughly do:
Send data -> wait for DataReceive to fire -> handle data -> repeat.
Just be sure to put a timeout in the waiting loop.
I am wondering how to send msg using serialport every x minutes. In the meantime app should be fully accessible. I just want to check printer status, so i'm sending every 5 minutes "Error status request" and if there are some errors - then sound alarm or something..
See http://msdn.microsoft.com/en-us/library/system.timers.timer.aspx
You can write to the serial port using c# fairly easily
http://msdn.microsoft.com/en-us/library/system.io.ports.serialport.aspx
The simplest way to perform an action every x minutes is to spawn a thread off and put in a loop which performs Thread.Sleep(30000). You need to build some control code in so that you can stop your thread from the main code
I'm using the Input Simulator library to simulate input to another application using C#, this uses the SendInput API calls. Does anyone know if there is a way I can monitor the windows message queue for the external application to see if those messages have been processed?
For example, let's say I want to send the keystrokes for the word "Hello" to notepad, but I don't want my application to continue until notepad has received and processed the input and the word "Hello" has appeared in the notepad window. We'll know this has happened once the keypress messages are no longer in the message queue for notepad, but I can't work out how to find that out.
I was using the .NET SendKeys class and using SendWait, but this seems unstable and causes occasional freezes in the external application, so after weeks of trying to fix that I'm looking for a new method.
Many thanks
You can't. Calling SendInput ultimately results in posted messages which are delivered asynchronously.
Why fake input to Notepad when you can send the text direct to the edit window? Not only would it be way simpler it would be robust and synchronous.
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?