9

想象一下,我将在 .NET 中进行异步调用,即 HttpWebRequest.BeginGetResponse,并且 HttpWebRequest 对象没有在更广泛的范围内被引用。垃圾收集器会破坏它并引起问题吗?

示例代码:

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..
    }
}

替代版本(请求作为 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..
    }
}
4

5 回答 5

11

如果任何活动线程包含对它的引用,或者如果它被静态引用(在这两种情况下都是直接或间接),则认为该对象是活动的并且不符合垃圾回收的条件。

在这两个示例中,异步 API 都会保留对您的请求的引用(在提交异步 IO 操作的线程池中),因此在完成之前不会被垃圾收集。

于 2009-01-07T18:58:05.227 回答
3

不,垃圾收集器不会给你带来麻烦。

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.

于 2009-01-07T18:58:48.957 回答
1

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)

于 2009-01-07T19:03:21.397 回答
0

在第一个示例代码中,如果不使用它,为什么要创建 Request?

无论如何,如果当前范围内的任何对象都不存在对对象的引用(直接或间接),GC可能会收集它。

因此,在您的第一个示例中,当程序退出 Main 方法时,请求仍在范围内(在另一个线程中),因此在异步调用结束之前不会被收集。在您的第二个示例中,线程池线程和您的代码都保留了对您的对象的引用,因此它显然也不会被收集。

于 2009-01-07T18:58:21.233 回答
0

通过异步调用的实现,该对象仍然被很好地引用——它需要维护所有打开请求的列表,以将传入数据与请求相关联。最有可能的是,.NET 使用全局(或类)变量来存储请求。

于 2009-01-07T18:58:29.237 回答