[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

microsoft.public.dotnet.framework

TcpClient BeginRead not spawning new thread

icomply

10/2/2008 10:22:00 AM

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/5OISYyS4RQIENT...

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
3 Answers

Peter Duniho

10/2/2008 10:49:00 AM

0

On Thu, 02 Oct 2008 03:22:11 -0700, icomply <kerplunkwhoops@yahoo.co.uk>
wrote:

> [...]
> 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?

This sounds like reasonable behavior to me.

At the very least, you should not expect a call to BeginRead() to
necessarily create a new thread. In fact, in most cases it won't.
Instead, it will initiate the i/o operation, and an already-existing
thread will dequeue an i/o completion event when the operation completes.

In the scenario you describe, apparently the i/o operation can be
completed immediately, and .NET doesn't bother to initiate an asynchronous
operation but instead simply completes it immediately. That seems fine to
me.

What this has to do with your apparent deadlock, I can't say. Your code
shouldn't rely on i/o operations being completed on any specific thread,
but in any case having an operation complete on the same thread on which
it was started seems to me more likely to reduce the chance of deadlock
than increase it. Though admittedly, it depends on the nature of the
lock, so if what you're waiting on isn't a synchronization object, but
rather some operation you expected your thread to finish after returning
from BeginRead(), then yes...that certainly could create a deadlock
situation.

Pete

Jeroen Mostert

10/2/2008 11:16:00 AM

0

icomply wrote:
> 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.

--
J.

icomply

10/2/2008 11:37:00 AM

0

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