views:

469

answers:

5

Imagine that I will make an async call in .NET, i.e. HttpWebRequest.BeginGetResponse, and the HttpWebRequest object isn't referenced at a broader scope. Will the Garbage Collector destroy it and cause problems?

Example code:

using System;
using System.Net;

public class AsyncHttpWebRequest
{
    void Main()
    {
        var Request = HttpWebRequest.Create("http://www.contoso.com");
        var result = Request.BeginGetResponse(GetResponseCallback, null);
    }

    private void GetResponseCallback(IAsyncResult AsyncResult)
    {
        // Do Something..
    }
}

Alternate version (with the request being passed as an AsyncState):

using System;
using System.Net;

public class AsyncHttpWebRequest
{
    void Main()
    {
        var Request = HttpWebRequest.Create("http://www.contoso.com");
        var result = Request.BeginGetResponse(GetResponseCallback, Request);
    }

    private void GetResponseCallback(IAsyncResult AsyncResult)
    {
        // Do Something..
    }
}
+9  A: 

An object is considered alive and non-eligible for garbage collection if any live thread contains a reference to it, or if it's referenced statically (directly or indirectly in both cases).

In both examples the async API keeps a reference to your request (within the thread pool where async IO operations are lodged) and so it won't be garbage collected until it completes.

Drew Noakes
A: 

In the first example code, why do you create Request, if you don't use it?

Anyway, if no reference (direct or indirect) exists to an object from any of objects currently in scope the GC may collect it.

So in your first example when the program exits Main method Request is still in scope (in another thread) so it will not get collected until the async call ends. In your second example, both, the thread-pool thread, and your code keep a referrence to your object, so it obviously won't get collected as well.

Krzysztof Koźmic
I use it, don´t you see?
Jader Dias
Yes, I see it. Fixed. I got confused by the coloring of the code ;)
Krzysztof Koźmic
A: 

The object remains referenced just fine, by the implementation of async calls - which needs to maintain a list of all open requests, to correlate incoming data to the requests. Most likely, .NET uses a global (or class) variable to store the requests.

Martin v. Löwis
+2  A: 

No, the garbage collector won't cause you problems.

Don't assume that because you don't have access to the object, the garbage collector is going to clean it up.

The garbage collector starts with a number of "roots" - objects and references that are known reachable. Then, all the objects reachable from those roots are found, and everything else is collected.

Each running thread - including the thread(s) that process the Async calls are included in the list of roots.

Bevan
A: 

If an object has no references as far as the GC is concerned then you can no longer get a reference to it. So you can't have an object that temporarily doesn't have a reference to it.

(This assumes nothing sneaky like unmanaged or unsafe code playing games)

BCS
In the second example I provided there is a interval of time where I can't see any reference to the Request object. This is what I meant by "temporarily unreferenced". What really happens is that the reference is hidden in some .NET object.
Jader Dias
My point is that the GC don't care what you can see, only what can seen by anyone. If anything can see it or will be able to see it (those are the same, I think) it won't collect it.
BCS