Re: async sockets and threading
- From: "Ben Voigt [C++ MVP]" <rbv@xxxxxxxxxxxxx>
- Date: Wed, 22 Oct 2008 09:31:16 -0500
Peter Duniho wrote:
On Tue, 21 Oct 2008 23:24:03 -0700, Alexander Gnauck
<gnauck@xxxxxxxxxxxxxx> wrote:
Peter Duniho wrote:
Please post a concise-but-complete code sample here.
ok, here is the example: [...]
Thanks for the example. With that in hand, it looks to me as though
the problem is related to garbage collection. In particular, it
appears that the JIT compiler figures out that you don't refer to the
_socket or _stream class members once the thread you started exits,
and it makes those members eligible for garbage collection. And of
course, when that happens (well, once the finalizer is run), the
connection winds up closed.
I added some synchronization to ensure that the Open() method doesn't
return until the EndSend() callback has been executed, and that
reliably makes the problem go away. That seems to confirm the GC as
the culprit.
What if you instead saved the IAsyncResult returned by BeginConnect into a
static variable? Perhaps that is what is being collected (though presumably
the same one gets passed to the completion routine)?
Now, whether that's _correct_ behavior, I'm not entirely sure. It
_seems_ like a .NET bug to me. In particular, those are static
members, and I would have thought all class static members would be
considered a root for the purpose of garbage collection. In fact,
one of the authoritative articles on .NET garbage collection seems to
say just that: " all the global and static object pointers in an
application are considered part of the application's roots" (from
http://msdn.microsoft.com/en-us/magazine/bb985010.aspx).
So, at the very least, for this code example, it seems to me that the
GC is prematurely collecting the objects. If your real-world
scenario also keeps the objects in static members, then the same bug
would be affecting you.
I think the BCL should be keeping these objects alive completely independent
of the user's references from static members. After all, the only living
reference could be in the State parameter to BeginConnect.
Of course, if in your real-world scenario, these objects wind up
referenced by instance members that are in a class instance that
itself becomes unreachable due to the use of the thread, then _that_
would be expected behavior. The fix there would be, of course, to
keep a reference to the instance storing the socket and stream
instances, so that they remain reachable and uncollected.
In that case, presumably the completion routine would be a instance method,
so the AsyncCallback delegate passed to BeginConnect would reference the
instance and (should) keep it alive.
In either case, I think that the static-based version of the behavior
is a bug, and it would be very helpful if you would post a bug report
to the http://connect.microsoft.com/ web site, for the .NET Framework.
Pete
.
- Follow-Ups:
- Re: async sockets and threading
- From: Peter Duniho
- Re: async sockets and threading
- References:
- async sockets and threading
- From: Alexander Gnauck
- Re: async sockets and threading
- From: Peter Duniho
- Re: async sockets and threading
- From: Alexander Gnauck
- Re: async sockets and threading
- From: Peter Duniho
- async sockets and threading
- Prev by Date: Re: C# - Static vs. Const
- Next by Date: Re: Code snippet
- Previous by thread: Re: async sockets and threading
- Next by thread: Re: async sockets and threading
- Index(es):
Relevant Pages
|