我自己和一位同事在.NET中垃圾收集对象时有不同的看法。看看下面的代码:.NET服务器垃圾收集和对象生命周期
Stream stream=getStream();
using(var request=new Request(stream))
{
Stream copy=request.Stream;
// From here on can "request" be garbage collected?
DoStuff1();
DoStuff2(copy);
}
我的同事声称,在发布版本中使用服务器垃圾收集器,它是有效的request
对象是调用request.Stream
后垃圾回收运行。他断言这只会发生在服务器垃圾收集器上,而不会发生在工作站垃圾收集器上。
之所以这样,是因为Request
类有一个终结器正在关闭给予请求的Stream
。因此,当DoStuff2
去使用流时,它得到了“对象处置”异常。由于终结器只能由垃圾收集器运行,所以我的同事说垃圾收集必须发生在finally块的末尾之前,但是在最后一次使用后request
但是,我相信自从上述代码只是速记是这样的:
Stream stream=getStream();
Request request=null;
try
{
Stream copy=request.Stream;
// From here on can "request" be garbage collected?
DoStuff1();
DoStuff2(copy);
}
finally
{
if(request!=null)
request.Dispose();
}
然后request
不能被垃圾调用request.Stream
后收集它仍然是来自finally
块到达。
另外,如果垃圾回收器有可能收集对象,则finally
块可能会显示未定义的行为,因为Dispose
将在GC对象上调用,这是没有意义的。同样,也无法优化掉finally
块作为异常可以在try
/using
块任何垃圾回收已经发生之前,这将需要finally
块执行中被抛出。
忽略终结器中关闭流的问题是否有可能垃圾收集器在finally
块的末尾之前收集对象,实际上优化finally
块中的逻辑?
你是对的,直到finally运行,请求才能被GCed。 – 2014-12-05 12:55:17
请注意,如果request.Dispose没有使用实例字段,请求*可以在对其调用Dispose之前收集。这是一种罕见的情况。 – usr 2014-12-05 12:58:06
建议:不要使用终结器。然后,这个问题就变得没有意义了。您无法在工作中检测到GC(除非通过非常不寻常的方式,例如终结器或调试API)。为什么Request.Finalize需要关闭流?流本身有一个终结器。 – usr 2014-12-05 12:59:11