想象一下,我将在.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..
}
}
答案 0 :(得分:11)
如果任何活动线程包含对它的引用,或者它是静态引用(在两种情况下都直接或间接引用),则该对象被视为活动且不符合垃圾回收条件。
在这两个示例中,异步API都会保留对您的请求的引用(在提供异步IO操作的线程池中),因此在完成之前不会对其进行垃圾回收。
答案 1 :(得分:3)
不,垃圾收集器不会给你带来麻烦。
不要认为因为你无权访问该对象,所以垃圾收集器会将其清理干净。
垃圾收集器以许多“根”开头 - 已知可达的对象和引用。然后,找到从这些根可到达的所有对象,并收集其他所有对象。
每个正在运行的线程 - 包括处理异步调用的线程都包含在根列表中。
答案 2 :(得分:1)
如果某个对象在GC方面没有引用,则您不能获取对它的引用。因此,您不能拥有暂时没有引用它的对象。
(这假设没有像玩游戏的非托管或不安全代码那样偷偷摸摸)
答案 3 :(得分:0)
在第一个示例代码中,如果您不使用它,为什么要创建Request?
无论如何,如果当前在范围内的任何对象中没有对象(直接或间接)存在参考,那么GC 可能会收集它。
因此,在您的第一个示例中,当程序退出时,Main方法仍然在范围内(在另一个线程中),因此在异步调用结束之前不会收集它。 在你的第二个例子中,线程池线程和你的代码都保持对你的对象的引用,所以它显然也不会被收集。
答案 4 :(得分:0)
通过异步调用的实现,对象仍然可以正常引用 - 它需要维护所有打开请求的列表,以将传入数据与请求相关联。最有可能的是,.NET使用全局(或类)变量来存储请求。