我想严格理解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
答案 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被卸载时,断点被击中。