GCHandle.Alloc(Object) 的契约到底是什么?

发布于 2024-12-08 19:32:51 字数 1030 浏览 0 评论 0 原文

我想对 GCHandle.Alloc(Object) 的契约有一个严格的理解。

我从文档中了解到,如果我调用:

GCHandle gc = GCHandle.Alloc(foo);

foo 将保证不会被垃圾收集,直到我调用:

gc.Free();

我还了解到,如果卸载 AppDomain,则 foo 将被收集。

我想检查的是,在不调用 Free 的情况下调用 Alloc 是否实际上与根引用相同(在 GC 看来)。

需要明确的是,如果这是真的,那么 GCHandle 变量 gc 的范围对 foo 的生命周期没有影响。如果 Free 不被调用,则 foo 会一直存在,直到 AppDomain 卸载。

例如 对象对自身调用 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

I'd like to have a rigorous understanding of the contract of GCHandle.Alloc(Object).

I understand from the documentation that if I call:

GCHandle gc = GCHandle.Alloc(foo);

foo will be guaranteed not to be garbage collected until I call:

gc.Free();

I also understand that foo will get collected if the AppDomain is unloaded.

What I would like to check is if a call to Alloc without a call to Free is effectively the same (in the eyes of the GC) as a root reference.

To be clear if this is true then the scope of the GCHandle variable gc has no impact on the lifetime of foo. If Free is not called foo lives until the AppDomain unloads.

E.g.
An object calls Alloc on itself and does not retain the GCHandle instance, it will live until the AppDomain is unloaded.

Is this correct?

Some references:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蔚蓝源自深海 2024-12-15 19:32:51

正确的。 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 调用期间都不会调用它。但是,当应用程序域被卸载时,就会命中断点。

Correct. The GCHandle variable has no effect on the lifetime of the object that you pass to GCHandle.Alloc(). I verified this with the following two classes:

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();
   }
}

And the following test code:

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();

Using this example, if you set a breakpoint in the Test class's finalizer, you will note that it is not called during any of the GC.Collect/WaitForPendingFinalizers calls. The breakpoint is hit, though, when the appdomain is unloaded.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文