Problem
The following subroutine is part of a client/server chat application written in VB .NET. The code below is part of the chat client. It runs in a separate thread from the main thread and listens indefinitely for incoming data from the chat server application. The problem is that when the application is closed, the process keeps running in the background. Please assist.
The chat client application contains a form with a button to connect to the chat server application via a TCP/IP socket connection:
The code “Dim ctThread As….” spawns a new thread that listens continuously (and indefinitely) for new incoming messages sent to listening clients by the chat server application.
Here you see the actual subroutine that is being run in a separate thread:
When you run the code in Visual Studio Express, you can step through the code, set breakpoints and see the familiar yellow marked line of text indicating the main thread code execution pointer.
When the chat client application is closed by closing the form, the process keeps running however. If I press CTRL-Break, I am presented with a green marked line of text indicating the sub-thread code execution pointer.
No matter what, it always seems to be executing instruction “serverStream=clientSocket.GetStream()”
I have to go into Task Manager and kill the chat client process to recover from this situation.
Can you assist please?
Solution
Multi-threading in VB .NET is challenging. Debugging multi-threading even more so. You need to thoroughly understand the concepts behind having multiple threads in an application. It is not good practice to simply ‘fire and forget’ threads. Interrupting threads, variable pass-through, joining threads all add to the learning curve.
This is a solution to gracefully terminate your sub-thread without relying on the main thread calling Thread.Abort():
As you can see, we have included serverStream.ReadTimeout. This will generate an error every second when the timeout value is reached. By putting the block of code in a Try…Catch handler, we can temporarily suspend listening for incoming data and probe our environment to see whether the main thread is still alive.
If the user had pressed the close button in the top right corner of Form1, the form would have closed and would no longer be visible. The sub-thread would still be running, so when the timeout causes the Try…Catch handler to kick in, we simply check if Form1 is still visible by using “If Me.Visible (= True) …”. If the form is not visible it means the application (main thread) was closed, and the sub-thread should close as well.