阅读 Richter J 的书中 "Monitoring and Controlling the Lifetime of Objects Manually" 部分。Jeffrey说,使用 GCHandle 类有两种方法可以“控制”对象的生命周期:
- 使用 GCHandleType.Normal 调用 Alloc 方法(即使应用程序代码中可能没有对对象的引用,GC也不能删除对象)
- 使用 GCHandleType.Pinned 调用 Alloc 方法(除了 Normal 模式,还可以防止 GC 移动这种对象)
他说,两种方法都可以用于将托管对象传递到非托管代码中。他试图解释开发人员何时应该使用带有 GCHandleType.Normal 标志的 Alloc。我并不真正理解有关 Normal 标志使用的解释。在两种方式中,我们都不允许 GC 收集具有此标志的对象,但在固定模式下,我们还可以在垃圾回收期间防止移动此类对象。据我所知,在普通模式下,并不直接将引用(内存地址)传递给非托管代码,而只是将 GC 描述符表中的索引传递给它。当非托管代码回调托管代码时,此索引将转换为当前/实际地址。我的头脑混乱,在 Google 和 Microsoft 中几乎没有详细信息,只有复制粘贴。
我的问题:
- 某些应用程序根(而不是弱)引用托管堆中的对象,没有更多的根。这意味着 GC 描述符表中相应的条目将具有 GCHandleType.Normal 标志吗?看起来并不是,因为 Jeffrey 说,“GC 不能删除对象,即使应用程序代码中可能没有对对象的引用。”但如果不是,那么这个表项会有哪个标志?同样,MyClass mc = new MyClass(),mc 在 GC 描述符表中对应的条目是否有 Normal 标志?如果不是,又是什么?
- 开发人员真正需要使用 GCHandleType.Normal 标志的时候是什么时候(以及如何,请给出简短的代码示例)?对于固定标志,我更清楚。
ToInt32()
会破坏与 x64 的兼容性。 - SupinePandora43