垃圾收集器是否在.NET中的异步调用期间销毁暂时未引用的对象?

时间:2009-01-07 18:50:43

标签: c# .net asynchronous garbage-collection

想象一下,我将在.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..
    }
}

5 个答案:

答案 0 :(得分:11)

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

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

答案 1 :(得分:3)

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

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

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

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

答案 2 :(得分:1)

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

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

答案 3 :(得分:0)

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

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

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

答案 4 :(得分:0)

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