Click here to Skip to main content
16,016,744 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I'm using an application in C # to communicate with a microcontroller. In this application I open the serial port and read data sent by a microcontroller through SerialPort.DataReceived event, so far so good, the problem is that when I close the serial port, with the microcontroller still communicating with the application, not always serial port is closed, and if I to stop communication from microcontroller with my application it is normally closed.

I've tried many things, and I'm currently using to close the serial port by another thread that is not the main thread, because I read an article on the internet that someone with the same problem that me used this method, and worked, but not always works with me.

This code is part of the method that is called to close the serial port.

C#
CheckForIllegalCrossThreadCalls = false;         
SPArduino.RtsEnable = false;
SPArduino.DtrEnable = false;   
Thread thrThreadClose = new Thread(new ThreadStart(ThreadClose));
thrThreadClose.Start();


This thread closes the serial port


C#
private void ThreadClose()
{
     SPArduino.Close();
     SPArduino.Dispose();
}
Posted
Comments
Sergey Alexandrovich Kryukov 26-Jun-12 15:48pm    
One note: CheckForIllegalCrossThreadCalls = false; is a big abuse; you should never do it as it is very dangerous. Instead, you should do all UI stuff in UI thread only, using Control.Invoke or Control.BeginInvoke on any other thread.
--SA
Sergey Alexandrovich Kryukov 26-Jun-12 16:01pm    
System.Windows.Forms? Tag "Forms" then.
--SA
SoMad 26-Jun-12 19:12pm    
How do you determine that the port is not closed?
Please see Sergey's solution and pay attention to the "Closing of the port..." paragraph. I would add that if the microcontroller is reading the signals in order to determine if the port is closed, be careful if you are using a virtual (USB) COM port. Some of them have problems accurately mirroring all the signal pin functionality of a real COM port.

Soren Madsen
Edson Rodrigues da Silva 27-Jun-12 17:41pm    
I know that the door is not closing because when I close and try to reopen it the C # displays an error message saying that the door is inaccessible, I'm using a port like COM, because I do not know how to create another type of serial port. How do I create another door? and because it would be better?
SoMad 27-Jun-12 20:44pm    
Ok, then it does sound like a handle or something is not being properly released.
When I talk about virtual COM ports, I mean a USB to serial port converter such as this USB RS232 Cables[^]. These are not better than serial ports on the motherboard, but they are quite useful if there are not enough serial ports available on the motherboard.

Soren Madsen

1 solution

The code you found on Internet is really bad. Also, please see my comment to the question.

You should do all the serial port communications in a separate thread; this way, you can close the port in the same thread. Also, I would advise you to use only the blocking calls (synchronous API, none of the asynchronous API). The asynchronous APIs flourished when thread were not such a commonplace as they are now (and even then they were questionable) and internally still use threads or something equivalent, anyway, but do not provide you with enough control. As using synchronous API is more sequential and straightforward, it's more effective, simpler, easier for maintenance and debugging.

Closing of the port per se does not tell anything about it to your microcontroller you have on the other end of the serial cable, so further considerations would need documentation on microcontroller to see how its communication channel behaves on the non-grace closing of the port (which is nothing wrong in principle, but depends on the code of the other side).

In these past answers, I describe how parameters are passed to the thread using a thread wrapper:
How to pass ref parameter to the thread[^],
change paramters of thread (producer) after it started[^].

As you are working with UI, it should be isolated from the serial communications. As you need to notify the UI and pass data from the serial port to it, you should use invocation mechanism which allows you to delegate the calls to UI methods and properties to the UI thread, which is the only valid way of working with UI. Please see my past answers for detailed explanations:

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[^].

If you want to understand how invocation works, my short article on the inter-thread invocation and blocking queue could be useful:
Simple Blocking Queue for Thread Communication and Inter-thread Invocation[^].

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
 
Comments
Maciej Los 26-Jun-12 18:54pm    
As always, well explained, my 5!
Sergey Alexandrovich Kryukov 26-Jun-12 19:03pm    
Thank you, Maciej.
--SA
Edson Rodrigues da Silva 27-Jun-12 17:45pm    
Thanks for your reply, I'll read the articles and if I have any questions I ask here again.
Sergey Alexandrovich Kryukov 29-Jun-12 18:34pm    
Good; and you are welcome. Consider accepting this answer formally (green button) -- thanks.
--SA

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