为什么使用FinalReleaseComObject而不是ReleaseComObject?

Mat*_*els 33 .net com interop

我知道基本的区别,因为ReleaseComObject只减少一些计数器并将其FinalReleaseComObject减少到零.

所以我通常听到的是,调用FinalReleaseComObject因为那时你确定COM对象真的被释放了.

但这让我想知道,这个反击有一点对吗?如果你总是打电话,你不打破这种机制吗FinalReleaseComObject?如果在您打电话之前该计数器不是一个,那么ReleaseComObject可能没有理由吗?

什么可能导致它高于一个不应该?

提前致谢.

PS:我的COM体验只包括使用Excel Interop.不确定这个问题是否属于该域的本地问题(即在Office Interop之外,FinalReleaseComObject不经常使用).

更新1

文章丹提及使用会谈ReleaseComObject时,即可大功告成.据我从文章中了解,这是正常的方式.我认为,如果你这样做,它应该工作正常.在对文章的评论中,作者建议有人ReleaseComObject在循环中调用直到它真正发布(该文章来自2006年,所以这与调用类似FinalReleaseComObject).但他也表示这可能是危险的.

如果你真的想让RCW在代码中的某个特定点调用Release(),你可以在循环中调用ReleaseComObject()直到返回值达到零.这应该确保RCW将调用Release().但是,如果您这样做,请注意,当其他托管引用尝试使用该RCW时,它将导致异常."

这让我相信总是打电话确实不是一个好主意FinalReleaseComObject,因为你可以在其他地方引起例外.正如我现在所看到的那样,如果你绝对确定可以,你应该只打电话给你.

不过,我对此事的经验不多.我不知道怎么可以肯定.如果计数器在不应该增加的情况下增加,那么解决这个问题是不是更好?如果是这样,那么我会说FinalReleaseComObject更多的是黑客而不是最佳实践.

Dan*_*ard 36

一些序言......

运行时可调用包装器(RCW)仅在其包装的非托管COM接口上调用IUnknown.AddRef一次.但是,RCW还维护RCW本身的托管引用数量的单独计数.这是托管引用的单独计数,通过调用Marshal.ReleaseComObject来递减.当托管引用的计数达到零时,RCW在非托管COM接口上调用IUnknown.Release一次.

Marshal.FinalReleaseComObject通过一次调用将托管引用计数设置为零,从而立即调用包装的非托管IUnknown.Release方法(假设托管引用计数不是零).

那么为什么要同时使用Marshal.ReleaseComObject和Marshal.FinalReleaseComObject?调用Marshal.FinalReleaseComObject只是避免了编写一个循环调用Marshal.ReleaseComObject的反复,直到它时,你想表明您已经返回0,真正使用的COM对象完成了现在.

为什么要使用Marshal.ReleaseComObject或Marshal.FinalReleaseComObject?我知道有两个原因:

第一个是确保由于对非托管IUnknown.Release()方法的调用而尽快释放被包装的COM对象使用的非托管资源(例如文件句柄,内存等).

第二个是确保调用非托管IUnknown.Release()方法的线程在您的控制之下,而不是终结器线程.

如果不调用任一方法元帅的RCW的终结将最终调用非托管IUnknown.Release()方法一段时间后RCW已被垃圾回收.

有关确凿的详细信息,请参阅Visual C++团队博客条目混合确定性和非确定性清理

  • 来自http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.marshal.releasecomobject.aspx上的"Marshal.ReleaseComObject Method"文档:"确保运行时可调用包装器和原始COM对象释放后,构造一个循环,从中调用此方法,直到返回的引用计数达到零." (3认同)