Close SerialPort open in another thread

Rkdobh

New member
Joined
Oct 8, 2019
Messages
2
Programming Experience
Beginner
Hello there.
I have a program that creates a thread which opens one SerialPort (let's say COM1). In some moment of my program I have to kill this thread (thread.Abort) but when I do that, that open serial port COM1 stays opened and unavailable.
How can I close any open serial port that some thread of my program has opened?

Thanks
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
2,431
Location
Sydney, Australia
Programming Experience
10+
You should avoid calling Thread.Abort if you possibly can but, if you're going to call it, you should have read the documentation for that method. As the documentation states, it throws a ThreadAbortException. That means that you can add appropriate exception handling and then cleanup in either the Catch or Finally blocks, depending on whether it needs to be done only on abort or in all cases.
 

Sheepings

Senior Programmer
Joined
Sep 5, 2018
Messages
466
Location
UK
Programming Experience
10+
This is what background workers are for, and in situations like yours, it could be really handy to implement one. Your RunWorkerAsync() will run in a new thread, and do whatever long running process you want it to complete. And when the worker switches to RunWorkerCompleted(), you will be back on your main thread where you can close the port that's no longer in work. The RunWorkerCompleted() method runs in your main thread. And it does this automatically after your DoWork method has completed its cycle. Further to clarify, If your BackgroundWorker is created on the UI thread, then the RunWorkerCompleted event will be raised on the UI thread when the worker is done working, and if you create the worker in a new thread, it will return to an arbitrary thread, so try to avoid that. See BackgroundWorker Class (System.ComponentModel) You can also pick up some tips from the SerialPort Class (System.IO.Ports) re how they use threading par example in docs.
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
461
Location
Virginia Beach, VA
Programming Experience
10+
OP: Are you aborting the thread because reading from the port is getting stuck, if so in the documentation linked to by Sheepings above, it says this:
If a SerialPort object becomes blocked during a read operation, do not abort the thread. Instead, either close the base stream or dispose of the SerialPort object.
 

Rkdobh

New member
Joined
Oct 8, 2019
Messages
2
Programming Experience
Beginner
This is what background workers are for, and in situations like yours, it could be really handy to implement one. Your RunWorkerAsync() will run in a new thread, and do whatever long running process you want it to complete. And when the worker switches to RunWorkerCompleted(), you will be back on your main thread where you can close the port that's no longer in work. The RunWorkerCompleted() method runs in your main thread. And it does this automatically after your DoWork method has completed its cycle. Further to clarify, If your BackgroundWorker is created on the UI thread, then the RunWorkerCompleted event will be raised on the UI thread when the worker is done working, and if you create the worker in a new thread, it will return to an arbitrary thread, so try to avoid that. See BackgroundWorker Class (System.ComponentModel) You can also pick up some tips from the SerialPort Class (System.IO.Ports) re how they use threading par example in docs.
Thanks, I'll read about it. In my case I have to be able to cancell the ongoing process and so close the serialPort. I'll try with background workers.
 

Sheepings

Senior Programmer
Joined
Sep 5, 2018
Messages
466
Location
UK
Programming Experience
10+
Note BackgroundWorker.CancellationPending is exactly for that, and while your DoWork is working, you occasionally check if cancellation is pending, and if it is, drop out of doing work. The docs I linked have all the information on this subject, so take your time reading over them. Of course, if you get stuck or need something explained, let us know.
 

jmcilhinney

C# Forum Moderator
Staff member
Joined
Apr 23, 2011
Messages
2,431
Location
Sydney, Australia
Programming Experience
10+
Note BackgroundWorker.CancellationPending is exactly for that, and while your DoWork is working, you occasionally check if cancellation is pending, and if it is, drop out of doing work. The docs I linked have all the information on this subject, so take your time reading over them. Of course, if you get stuck or need something explained, let us know.
Don't know for sure but I'm guessing that that won't be possible because the SerialPort is likely at a blocking call.
 

Sheepings

Senior Programmer
Joined
Sep 5, 2018
Messages
466
Location
UK
Programming Experience
10+
@jmcilhinney I'm not at a PC right now, but once I get home, and find some free time. I will check it out and let you know.

If a port is non-responsive or blocked, it might be best to dispose.

Reply from mobile
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
461
Location
Virginia Beach, VA
Programming Experience
10+
What jmcilhinney is trying to say is that there is no way to check (within the same worker thread/thread pool thread) while you are blocked. Given the following code how can you get back to the while condition if serialPort.Read() is blocked:
Code:
while (!worker.CancellationPending)    // initially not cancelled, so go to read below
{
    :
    serialPort.Read(...);    // while blocked here, the worker.CancelAync() has been called on the UI thread.
    :
}
 

Sheepings

Senior Programmer
Joined
Sep 5, 2018
Messages
466
Location
UK
Programming Experience
10+
I digress, so let me quickly clarify as I am pushed for time, as the above code you posted is not what I was considering...(I guess; my fault for not being elaborate enough.)

...and while the above code example you posted is a valid example of what you thought i meant, yes, you are correct regarding that snipped. But it is still possible to check with a separate thread and implement fail safes to poll against the backgroundworker and check if the while loop is still reporting execution, because I just did it.

In a non-serialports standard case, you could declare a private int to act as a ticker for the while loop or simply use a stop watch, and while your while loop is read/writing, and the private int is not more than its last value within a given time-frame, this would indicate the worker may be blocked by the executing code. In the case of serialports, this private int would be instead bytes read/written so far. you should be checking bytes read/written... SerialPort.BytesToRead Property (System.IO.Ports)

IO.Ports also have timeouts SerialPort.ReadTimeout Property (System.IO.Ports) which should be used instead. Frankly, if a user is read/writing something, it should know how long it will take, and if it exceeds the timeout, you could simply dispose of it if you exhausted other avenues offered by the documentation, like checking handshake, timeout, bytes written/read so far etc. This is also worth a read : Some serialport tips Top 5 SerialPort Tips [Kim Hamilton] And since our OP hasn't posted their code, there is nothing for us to compare against.
 

Skydiver

Well-known member
Joined
Apr 6, 2019
Messages
461
Location
Virginia Beach, VA
Programming Experience
10+
Yes, take advantage of timeouts as well as the data available events.
 
Top Bottom