Threading newbie problem: How do I join once a thread is done?

M

Matthew Speed

I've written a TCP/IP server. The main loop in the code looks like
this:

While Not shutdown
Console.WriteLine("Listening for connection...")

Dim svrsocketforclient As Socket = tcpl.AcceptSocket

svrsocketforclientthread = svrsocketforclient
Console.WriteLine("Connection from {0} at {1}",
svrsocketforclient.RemoteEndPoint, Now())
Dim clientthread As Thread = New Thread(AddressOf
createclientthread)
clientthread.Start()


End While

Thsi works great. Clients connect, threads spawn and go off and do
work. The problem I have is I cannot figure out how to get the
threads to rejoin once they are done. My clients gracefully log off
and I execute a .Close method at the end of the thread code but then
it just goes into limbo. As a result the app uses more and more CPU
cycles until my 2.4 Ghz P4 feels like a 286.

Any help would be greatly appreciated.
 
T

Tom Shelton

I've written a TCP/IP server. The main loop in the code looks like
this:

While Not shutdown
Console.WriteLine("Listening for connection...")

Dim svrsocketforclient As Socket = tcpl.AcceptSocket

svrsocketforclientthread = svrsocketforclient
Console.WriteLine("Connection from {0} at {1}",
svrsocketforclient.RemoteEndPoint, Now())
Dim clientthread As Thread = New Thread(AddressOf
createclientthread)
clientthread.Start()


End While

Thsi works great. Clients connect, threads spawn and go off and do
work. The problem I have is I cannot figure out how to get the
threads to rejoin once they are done. My clients gracefully log off
and I execute a .Close method at the end of the thread code but then
it just goes into limbo. As a result the app uses more and more CPU
cycles until my 2.4 Ghz P4 feels like a 286.

Any help would be greatly appreciated.

Personally, if I were you I would use the async socket methods for your
server (look for the BeginXXX/EndXXX pairs).

But still, what does your client trhead method look like? When a thread
method ends, the thread dies... So, I'm not sure what you mean by
limbo.
 
P

Peter Huang

Hi Matthew,

From your description, I understand that you wants to make a multithread
tcp socket server in .net
Have I fully understood you? If there is anything I misunderstood, please
feel free to let me know.

Here is a sample you may take a look.
http://www.gotdotnet.com/Community/UserSamples/Details.aspx?SampleGuid=75e68
966-d567-47b3-a255-9a51f9cb0eb7

Please apply my suggestion above and let me know if it helps resolve your
problem.

If you have any concern on this issue, can you post your clientthread
function here for us to do further troubleshooting.


Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

Matthew Speed

Thank you for your help. I hope I am using it correctly but I found a
line in that sample that looked like

Threading.Thread.CurrentThread

I didn't know a thread "knew" of its own existence or if it did, how
to access it (I did say I was a threading newbie) but now that I know
this it gave me a direction to go and I think my solution is sound.

I added that line and discovered that it has a .Join() method. It
doesn't appear to have any ill effects and since it does reference the
current thread my assumption is that if this command is run when a
thread is finished that it will in fact be joined to the main thread
wihtout impacting other threads. If this is incorrect I would
appreciate someone letting me know quickly.
 
C

CJ Taylor

I was pretty sure that the Join method blocked the calling thread from
executing any further till a AutoResetEvent had been flagged. (.ie. the
thread completed its task and exited gracefully.).

Could be wrong. something to look into.

-CJ
 
P

Peter Huang

Hi Matthew,

As Taylor said, when you call the ThreadB.Join method in Thread A, the
Thread A will be blocked until the Thread B has terminated.

Blocks the calling thread until a thread terminates

Thread.Join Method
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/
frlrfsystemthreadingthreadclassjointopic.asp

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

Matthew Speed

Hi Matthew,

As Taylor said, when you call the ThreadB.Join method in Thread A, the
Thread A will be blocked until the Thread B has terminated.
In my program, the main thread spawns the child threads. It is the
child, not the parent that calls Threading.Thread.CurrentThread.Join()

My simplified code looks like this:

Public Class MyTCPIPServer
public svrsocketforclient as socket

Public Sub StartListener()
tcpl = New TcpListener(IPAddress.Any, 2112)
tcpl.Start()

While Not shutdown
Console.WriteLine("Listening for connection...")

Dim svrsocketforclient As Socket = tcpl.AcceptSocket

svrsocketforclientthread = svrsocketforclient
Console.WriteLine("Connection from {0} at {1}",
svrsocketforclient.RemoteEndPoint, Now())
Dim clientthread As Thread = New Thread(AddressOf
createclientthread)
clientthread.Start()

End While
End Sub


Private Sub createclientthread()
Dim serversocketforclient As Socket
serversocketforclient = svrsocketforclientthread

' A bunch of database work commented out

serversocketforclient.Close()
Threading.Thread.CurrentThread.Join()

End Sub
End Class

So when the thread is finished doing its work it closes the socket it
was passed as an argument to ...New Thread in the StartListener sub
and then it joins itself to the main thread. To me this looks like
thread "B" is calling the .Join(), not thread "A" (the spawning
thread.) Am I misunderstanding what is actually happening?
 
P

Peter Huang

Hi Matthew,

I think there is some flaws in the program.
Private Sub createclientthread()
Dim serversocketforclient As Socket
serversocketforclient = svrsocketforclientthread

' A bunch of database work commented out

serversocketforclient.Close()
Threading.Thread.CurrentThread.Join()

'The code line above will block the current thread, in this way, the client
thread will never terminated.
End Sub
End Class
Public Sub StartListener()
tcpl = New TcpListener(IPAddress.Any, 2112)
tcpl.Start()

While Not shutdown
Console.WriteLine("Listening for connection...")

Dim svrsocketforclient As Socket = tcpl.AcceptSocket

svrsocketforclientthread = svrsocketforclient
Console.WriteLine("Connection from {0} at {1}",
svrsocketforclient.RemoteEndPoint, Now())
Dim clientthread As Thread = New Thread(AddressOf
createclientthread)
clientthread.Start()
' We need to call the clientthread.Join here, which will block the current
threads until the client thread terminated. But in this way, the TCP server
will not accepted the second request, because it will block on the
clientthread.join method. Or you do not need to call the clientthread.Join,
so that the main thread will not blocked. But you need to control the
connections from the clients, so that there will not be too many threading
running which will cause the performance hit.
End While
End Sub

So I think the sample will be a good practive to do the mulple threads TCP
server. Do you have any concern to try to sample?


Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

Matthew Speed

I think there is some flaws in the program.
'The code line above will block the current thread, in this way, the client
thread will never terminated.
Now I am completely confused. The StartListener is the main "body" of
the program. If run this in debug mode it sits on the .AcceptSocket
line waiting for a client to connect. As soon as one does, it creates
another thread, finishes the while loop (which returns to the
..Acceptsocket line to await another client)

Meanwhile, code execution in the spawned thread jumps to the
createclientthread sub. If I put an F9 on the .Join line, when code
execution pauses there I hit F11 to step forward and the sub just ends
and execution goes nowhere.

I can still continue connecting clients to the server so I don't
understand what "blocking" refers to. My program appears to be
working without problem

Is there some reference I can read to really understand what is going
on with Threads?
 
P

Peter Huang

Hi Matthew,

I am sorry if I did not make clarification.

If you call the Threading.Thread.CurrentThread.Join() in the new started
thread, i.e. the client thread, the client will be blocked. You may try to
run the code below.
The line, Console.WriteLine(Threading.Thread.CurrentThread.Name + "
End")
will not be execute, because the client thread will be blocked on the the
line.
Threading.Thread.CurrentThread.Join()

Module Module1
Public Sub ThreadProc()
Console.WriteLine(Threading.Thread.CurrentThread.Name + " Start")
Threading.Thread.CurrentThread.Join()
Console.WriteLine(Threading.Thread.CurrentThread.Name + " End")
End Sub

Sub Main()
Console.ReadLine() 'Wait for input, press Enter to continue
Dim th As New Threading.Thread(AddressOf ThreadProc)
th.Name = "Client Thread"
th.Start()
Threading.Thread.Sleep(3000)
Console.WriteLine("Main Thread Exit")
End Sub
End Module

But in the above code we use the code line Threading.Thread.Sleep(3000) to
wait for the client thread to exit, but this can not guarantee the client
will complete its execution in 3 seconds.

So we usually use the Thread.Join to wait the Client to exit, in this way
,the thread which call the Thread.Join (wait for the specified thread to
exit) will block until the thread he is waiting for terminated.

Module Module1
Public Sub ThreadProc()
Console.WriteLine(Threading.Thread.CurrentThread.Name + " Start")
Threading.Thread.Sleep(3000)
Console.WriteLine(Threading.Thread.CurrentThread.Name + " End")
End Sub

Sub Main()
Console.ReadLine() 'Wait for input, press Enter to continue
Dim th As New Threading.Thread(AddressOf ThreadProc)
th.Name = "Client Thread"
th.Start()
th.Join()
Console.WriteLine("Main Thread Exit")
End Sub
End Module

You may try to uncomment the 'th.Join(), which will guarantee the line
Console.WriteLine("Main Thread Exit") will be executed until the Client
Thread terminated. If we do not call the th.Join, then the main thread will
exit when the working thread is in use.

So if there are more than one working threads in the meantime, I suggest
you use the ThreadPool using which the .net Framework will save your
efforts to synchronize the threads.

Managed and Unmanaged Threading in Microsoft Windows
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconmanagedunmanagedthreadinginmicrosoftwindows.asp

WaitForSingleObject on the thread handle Thread.Join

From the table we will know that the Thread.Join is the equivalent doing
WaitForSingleObject on the thread handle.

Using Threads and Threading
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconusingthreadsthreading.asp

Threads and Threading
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpguide/htm
l/cpconthreadsthreading.asp

Programming the Thread Pool in the .NET Framework
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/ht
ml/progthrepool.asp

Best regards,

Peter Huang
Microsoft Online Partner Support

Get Secure! - www.microsoft.com/security
This posting is provided "AS IS" with no warranties, and confers no rights.
 
M

Matthew Speed

Okay, I think that makes sense. I'll enter that code and run it so
that I understand what it is doing to integrate into my program.
Thanks for all your help.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top