想象一下,我将在.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..
    }
}
有帮助吗?

解决方案

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

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

其他提示

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

不要认为因为无权访问该对象,所以垃圾收集器会将其清理干净。

垃圾收集器以许多“根”开头。 - 已知可到达的对象和引用。然后,找到从这些根可到达的所有对象,并收集其他所有对象。

每个正在运行的线程 - 包括处理异步调用的线程都包含在根列表中。

如果某个对象在GC方面没有引用,则您不能再获取对它的引用。因此,您不能拥有临时没有引用它的对象。

(这假设没有像玩游戏的非托管或不安全代码那样偷偷摸摸)

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

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

无论如何,如果当前在范围内的任何对象中没有对象(直接或间接)存在参考,那么GC 可能会收集它。

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

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top