TcpClient BeginRead not spawning new thread

  • Thread starter Thread starter icomply
  • Start date Start date
I

icomply

Hello

I have a server app that uses System.Net.Sockets.TcpClient to allow
many clients apps to connect to it.

The server listens for message from the clients and performs an action
depending on the message.

I have had the server running for several days, after which one of the
client objects on the server ran into a thread deadlock. I attached
the debugger to the app and looked at the threads to determine what
had cause the deadlock.

I noticed that on one of the deadlocked threads I was calling
GetStream.BeginRead. I assumed this would spawn a new thread from the
thread pool and would execute the function passed in 'callback as
ASyncCallback'. However, when I looked at the callstack for the thread
it read 1:BeginRead, 2:callback function, 4:BeginRead, 5:callback
function. I do restart the BeginRead process in the callback function
to get the next message, but what surprised me was the the callback
function was being executed on the same thread that called BeginRead
and does not spawn a new thread.

Here is an image of the callstack for one of the threads
(blnBeginTCPRead calls GetStream.BeginRead and my ASyncCallback
function is ReceiveMessageFromClient):

http://vvcap.net/db/5OISYyS4RQIENTo6YHiX.htm

Can anyone confirm this is the correct behaviour of BeginRead? Should
I assume that BeginRead can actually execute the callback function
within the BeginRead statement, and on same thread? Could something
else I do cause this to happen? Is the thread pool being corrupted?

Many thanks

Paul Bell
 
icomply said:
Can anyone confirm this is the correct behaviour of BeginRead? Should
I assume that BeginRead can actually execute the callback function
within the BeginRead statement, and on same thread?

Yes, absolutely. In general, you can only assume that asynchronous
operations will not block indefinitely, which is the main reason for using
them. If an asynchronous operation can be completed immediately (because
buffered data is available) or within a very short amount of time (by
polling for a very short amount of time) then some operations will be
completed synchronously, because that's faster than spinning off a new thread.

If you get into trouble when this happens, you should rethink your design.
If nothing else, you could use the CompletedSynchronously property of your
IAsyncResult in the callback to see if you're (possibly) running on the same
thread as the one that initiated the request, and take appropriate measures.

If all else fails, you can always change your delegate to execute its code
on a thread pool thread instead (ThreadPool.QueueUserWorkItem()) but that's
not a very elegant solution.
 
Thanks for all your help.

I just needed this clarifying because I created locks which depended
on the call to BeginRead being released immediately. I can change my
design to accomodate this.

Paul
 
Back
Top