GCHandle.Alloc(对象)的合同究竟是什么?

时间:2011-10-07 13:57:38

标签: .net garbage-collection

我想严格理解GCHandle.Alloc(对象)的合同。

我从文档中了解到,如果我打电话:

GCHandle gc = GCHandle.Alloc(foo);
在我打电话之前,

foo将保证不被垃圾收集:

gc.Free();

我也理解,如果卸载AppDomain,将收集foo。

我想检查的是,如果没有调用Free的Alloc调用实际上与root引用有效(在GC的眼中)。

要清楚这是否属实,那么GCHandle变量gc的范围对foo的生命周期没有影响。如果在AppDomain卸载之前没有调用Free,则会生效。

E.g。 一个对象本身调用Alloc并且不保留GCHandle实例,它将一直存在直到AppDomain被卸载。

这是对的吗?

一些参考文献:

http://msdn.microsoft.com/en-us/library/a95009h1.aspx

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.gchandle.free.aspx

http://blogs.msdn.com/b/clyon/archive/2005/03/18/398795.aspx

1 个答案:

答案 0 :(得分:1)

正确。 GCHandle变量对传递给GCHandle.Alloc()的对象的生命周期没有影响。我用以下两个类验证了这一点:

class Test
{
   public Test ()
   {
      System.Runtime.InteropServices.GCHandle.Alloc(this);
   }
   ~Test ()
   {
   }
}
class Server : MarshalByRefObject
{
   public Server ()
   {
      new Test();
   }
   public void Collect ()
   {
      GC.Collect();
      GC.WaitForPendingFinalizers();
   }
}

以下测试代码:

AppDomain ad = AppDomain.CreateDomain("test");
Server svr = (Server)ad.CreateInstanceAndUnwrap(
   System.Reflection.Assembly.GetExecutingAssembly().FullName, 
   typeof(Server).FullName);
for (Int32 i = 0; i < 100; i++)
   svr.Collect();

使用此示例,如果在Test类的终结器中设置断点,您将注意到在任何GC.Collect / WaitForPendingFinalizers调用期间都不会调用它。但是,当appdomain被卸载时,断点被击中。