Mulitthreading Blues!

J

John Shelley

All these years of programming without multithreading, sure puts me at a
disadvantage here...Now I'm thrust into a big VB.NET project with
multi-threading all over the place, and I'm trying to sort it all out...

Two types of threads, right? A process thread (create a new thread object
and call the start method) and a thread pool thread (call the
QueueUserWorkItem method from the ThreadPool class). Then there are the
mystery threads... the ones that are 'built into' multi-threaded procedure
calls... you know, the ones that have method names like 'BeginConnect' or
'BeginRead'.

So there's my first question, I guess: Which type of thread do those use?

Second question: How can I tell, for sure, when a thread is released?

Third question: Do worker threads behave differently if they are created
off a process thread than when they are created off an existing worker
thread?
 
T

Tom Shelton

All these years of programming without multithreading, sure puts me at a
disadvantage here...Now I'm thrust into a big VB.NET project with
multi-threading all over the place, and I'm trying to sort it all out...

Two types of threads, right? A process thread (create a new thread object
and call the start method) and a thread pool thread (call the
QueueUserWorkItem method from the ThreadPool class). Then there are the
mystery threads... the ones that are 'built into' multi-threaded procedure
calls... you know, the ones that have method names like 'BeginConnect' or
'BeginRead'.

So there's my first question, I guess: Which type of thread do those use?

In general, they use the ThreadPool threads. In other words, the pull from
the same pool as the ThreadPool.QueueUserWorkItem method.
Second question: How can I tell, for sure, when a thread is released?

Not sure what you mean? You can queuery a threads state to see if it's
running, sleeping, stopped, etc. Look at the ThreadState property.
Third question: Do worker threads behave differently if they are created
off a process thread than when they are created off an existing worker
thread?

Not that I've ever noticed :) I haven't ever seen anything in the docs
that would indicate that there is a difference either.
 
C

Crirus

Second question: How can I tell, for sure, when a thread is released?
A thread is released when it's start method finish

If yuo need to check from another thread, there are some status methods on
thread
 
J

John Shelley

Thanks for your answers... let me get a bit deeper into
the issue then. I'm doing some custom socket-
communications. I basically used the on-line help
examples to build this app. It all works fine and dandy..
UNTIL I set up a test program and simulated mulitiple
requests coming in at the same time.

My understanding is, this: BeginAccept just gets the ball
rolling and passes off a new socket which I use from there
on out. BeginReceive says, ok, let's get the conversation
going. Then you loop through BeginReceive building your
message if it is over your buffer size. At this point,
you process the message and send a response using
BeginSend. (My code is listed at the bottom of this
message.)

In my testing, I just put a do-loop in that ties up the
BeginReceive thread for a couple of seconds to simulate a
long database run. So, my first request comes in fine,
tracks all the way through to the 'processing' stage. I
send in a second request and it goes ok, but the third
request does not get processed until my simulation gets
finished.. now this is EXACTLY what I'm supposed to be
avoiding, right?

Multi-threading is a real pain to debug, of course, but I
managed to watch the thread ID's for this operation, and
indeed, as expected, they are all starting on separate
threads.... Why I asked the question about when are they
released, is because I'm guessing the reason it stops on
the third call is it has run out of threads. (just a
guess.)

Could this have anything to do with the new worker threads
being created inside another worker thread? I
shouldn't... Or is it all the ManualResetEvents I'm using?

Any help or comments would be appreciated. Here is the
code:

---------------------------------------------------------
Public Sub Listen(ByVal State As Object)
Try
' get the localendpoint
Dim Socket As New Socket
(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType.Tcp)

'open the port and start listening
Socket.Bind(BS3.Common.GetLocalEndPoint
(Port))
Socket.Listen(200)

While True
Stopper1.Reset()
'wait for something to arrive
Socket.BeginAccept(New AsyncCallback
(AddressOf RequestReceived), Socket)
Stopper1.WaitOne()
End While
End Sub

Private Sub RequestReceived(ByVal AR As
IAsyncResult)
Try
Receiving1 = True
Stopper1.Set() 'allow main thread to
continue and handle next incoming request

Dim Socket1 As Socket = CType
(AR.AsyncState, Socket)

'extract the sending socket
Dim Socket As Socket = Socket1.EndAccept
(AR)
Dim MH As New MessageHolder
MH.WorkSocket = Socket

Stopper2.Reset()
'start getting the message
Socket.BeginReceive(MH.Buffer, 0,
MH.BufferSize, 0, AddressOf ReadRequest, MH)
Stopper2.WaitOne()

End Sub

Private Sub ReadRequest(ByVal AR As IAsyncResult)

Dim mysocket As System.Net.Sockets.Socket
Try
Receiving2 = True
Stopper2.Set()

Dim MH As MessageHolder = CType
(AR.AsyncState, MessageHolder)
' extract the sending socket
mysocket = MH.WorkSocket
Dim M As Byte()
' Read data from the server
Dim bytesRead As Integer =
mysocket.EndReceive(AR)

If bytesRead > 0 Then

' There might be more data, so store
the data received so far.
MH.MS.Write(MH.Buffer, 0,
bytesRead) 'appends data to the memorystream
If EndOfMessage(M()) then
Dim Response() as byte =
Ascii.GetBytes("Here is my response.")

'simulate database run here
Dim n As Date = Now
Do Until n < DateAdd
(DateInterval.Second, -10, Now)

Loop

' Send response
sendDone.Reset()
mysocket.BeginSend(Response,
0, Response.Length, 0, AddressOf SendCallback, mysocket)


sendDone.WaitOne()
End If
Else
'not finished, get more
mysocket.BeginReceive(MH.Buffer,
0, MH.BufferSize, 0, AddressOf ReadRequest, MH)
End If
End If
End Sub

Private Sub SendCallback(ByVal ar As IAsyncResult)

Try
CType(ar.AsyncState,
System.Net.Sockets.Socket).EndSend(ar)
Catch ex As Exception
CallBack.Invoke(CallBackEventTypes.Error,
ex.Message, ex.StackTrace)
Finally
sendDone.Set()
End Try

End Sub 'SendCallback
End Class
 
Z

ZorpiedoMan

Crirus -

Thanks for the sample... I think I have spotted the difference. On your
'Listener' class, you only use ONE ManualResetEvent, where I used three.
For some reason, I was following the format of the Client-Side (sending
side) when I designed my listener (server) which DOES have three
ManualResetEvent Objects.

I could have sworn that I followed the help examples to a tee, but I
went back and looked them up, and they are like yours, with only the one
MRE.... so, I must be stopping things with those... I'm going to take them
out and see how things work... I'll let you know.


-js
 
Z

ZorpiedoMan

No Luck...

the loop that simulates the database run is still tying everything up, even
though it is on a separate thead!!

This is driving me nuts.. no wonder they never let us VB guys do
multi-threading before!!! :)

-js
 
C

Crirus

You must be doing something wrong... That work hard simulation I made it
with a 10 seconds sleep... and the next calls was processed just fine

You say that your listener dont creat next thread for another call?
 
P

Peter Huang

Hi John,

I think you may try to write some information to a log file
[e.g. <Time>: function call succeed or failed, what is status of the
current synchronize object(ManualResetEvent)]
after every function call to troubleshoot what code line cause the
application hang.
the loop that simulates the database run is still tying everything up, even
though it is on a separate thead!!
Do you mean you want to do a database issue or asynchronized Client/Server
application?


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.
 

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