Click here to Skip to main content
15,868,141 members
Please Sign up or sign in to vote.
2.00/5 (1 vote)
See more:
hello everyone, first excuse my english, i'll try to be the most comprensible I can.

I'm developing an Arduino interface whose purpose is to show in a textbox the information abouth serial port.

the matter is that when I print the information into the text box traught the invoke, the form became slow or crash.

I'm reading from serial port using a background worker.

C#
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            while (serialPort1.IsOpen)
            {
                textBox1.Invoke((MethodInvoker)(() => textBox1.Text = serialPort1.ReadLine()));
            }
        }


how can I print the result of serialPort1.ReadLine() without making the application slow ?

thanks
Simone.
Posted
Comments
[no name] 26-Jun-14 21:00pm    
Why are you not using the DataRecieved event?
Sergey Alexandrovich Kryukov 26-Jun-14 23:21pm    
What do you mean "print"? on a printer? How is that related to the cross-thread operation speed (it's apparent that you need different threads and some inter-thread communications)?
—SA
George Jonsson 26-Jun-14 23:45pm    
I think it means print to the text box.
Sergey Alexandrovich Kryukov 27-Jun-14 1:04am    
Yes, of course; I'm just kidding. My answer remains the same... :-)
—SA
George Jonsson 27-Jun-14 2:29am    
Well, you never know what people really mean. :-P

I got it: you have done the worst abuse of UI and Invoke I ever saw. You need to do the opposite: do all serial communication in the server thread, use Invoke to show data in UI (or doing anything with UI).

You cannot call anything related to UI from non-UI thread. Instead, you need to use the method Invoke or BeginInvoke of System.Windows.Threading.Dispatcher (for both Forms or WPF) or System.Windows.Forms.Control (Forms only).

You will find detailed explanation of how it works and code samples in my past answers:
Control.Invoke() vs. Control.BeginInvoke()[^],
Problem with Treeview Scanner And MD5[^].

See also more references on threading:
How to get a keydown event to operate on a different thread in vb.net[^],
Control events not firing after enable disable + multithreading[^].

—SA
 
Share this answer
 
You can try this approach instead using the events of the SerialPort class.

Then there is no need to work in a loop.

Add this method to your main class
C#
public delegate void UpdateTextBoxDelegate(string text);
private void UpdateTextBox(string text)
{
  if (textBox1.InvokeRequired)
  {
    textBox1.BeginInvoke(new UpdateTextBoxDelegate(UpdateTextBox), text);
  }
  else
  {
    textBox1.Text = text;
  }
}


Add this event to your main class.
C#
this.serialPort1.DataReceived += new System.IO.Ports.SerialDataReceivedEventHandler(this.serialPort1_DataReceived);


Inside the event you add the code to set the value in the text box.
C#
private void serialPort1_DataReceived(object sender, System.IO.Ports.SerialDataReceivedEventArgs e)
{
    if (e.EventType == System.IO.Ports.SerialData.Chars)
    {
        UpdateTextBox(serialPort1.ReadLine());
        or
        UpdateTextBox(serialPort1.ReadExisting());
    }
}
 
Share this answer
 
v3
Comments
Sergey Alexandrovich Kryukov 27-Jun-14 1:06am    
Yes, of course, but I think the look and a separate thread is always better. You can use the same logic of inter-thread communication/synchronization over and over, while all those async. APIs are specific...
—SA
George Jonsson 27-Jun-14 2:27am    
I would say it depends on how often data appears on the COM port and also how the event is fired in the code behind.
If you have stream of data I agree a loop in a separate thread is to prefer.
Both ways will work.
/George
Sergey Alexandrovich Kryukov 27-Jun-14 2:32am    
Right...
—SA
Even though the serial port operation is fairly simple and using serial communication in a separate thread is quite reasonable, the question is not clear at all. Please see my comment to the question.

Answering just to the header of the question: it does not make much sense, just because all you serial port transport is (figuratively speaking) infinitely slower than any thinkable inter-thread communications. And if by "printing" you mean using a printer, it is also infinitely slower. :-)

So, if you have any concerns of the performance of the software, please explain your particular concerns. I don't think there is a reason to worry about it. If you really managed to make your application too slow, please provide more information.

—SA
 
Share this answer
 
There is a simple mistake in the code.

What it should do
1) read serial port on the background thread
2) update the textbox on the UI thread

What the code actually does
1) read serial port on the UI thread
2) update the textbox on the UI thread

If you separate the reading part from the updating part then the code will work as intended.
C#
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
{
  while (serialPort1.IsOpen)
  {
    textBox1.Invoke((MethodInvoker)(() => textBox1.Text = serialPort1.ReadLine()));    
    string data = serialPort1.ReadLine();
    textBox1.Invoke((MethodInvoker)(() => textBox1.Text = data));
  }
}


Alan.
 
Share this answer
 
Comments
George Jonsson 27-Jun-14 4:40am    
Missed that one.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900