发布COM组件
当您不再需要通过调用 Marshal.ReleaseComObject(..) 来释放 COM 组件时,是否真的有必要从 Office PIA 中释放它们?
我在网上发现了关于这个主题的各种相互矛盾的建议。 在我看来,由于 Outlook PIA 总是返回对其接口的新引用作为从其方法返回值,因此没有必要显式释放它。 我对吗?
Is it really necessary to release COM components from Office PIA, when you don't need them anymore by invoking Marshal.ReleaseComObject(..)?
I found various and contradictory advices on this topic on the web. In my opinion, since Outlook PIA is always returning a new references to its interfaces as returning values from its methods, it is not necessary to explicitly release it. Am I right?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
对于 VS 2010,请参阅Marshal.ReleaseComObject 被视为危险。
For VS 2010, see Marshal.ReleaseComObject Is Considered Dangerous.
对于 Microsoft Office,一般来说,您确实需要显式释放引用,这可以分两个阶段安全地完成:
(1) 首先通过调用 GC 释放您不持有命名对象变量的所有次要对象。 Collect() 然后是 GC.WaitForPendingFinalizers()。 (如果所涉及的对象可能具有终结器,例如使用 Visual Studio Tools for Office (VSTO) 时,则需要调用此两次。)
(2) 然后通过调用 Marshall 显式释放持有命名变量的对象每个对象上的.FinalReleaseComObject()。
就是这样。 :-)
我更详细地讨论了这个问题 之前的帖子,以及代码示例。
With Microsoft Office, in general, you do need to explicitly release your references, which can be safely done in two stages:
(1) First release all the minor object to which you do not hold a named object variable via a call to GC.Collect() and then GC.WaitForPendingFinalizers(). (You need to call this twice, if the objects involved could have finalizers, such as when using Visual Studio Tools for Office (VSTO).)
(2) Then explicitly release the objects to which you hold a named variable via a call to Marshall.FinalReleaseComObject() on each object.
That's it. :-)
I discussed this in more detail in a previous post, along with a code example.
PIA 是 .NET 互操作包装器。 这意味着在对象的析构函数(或 Dispose - 我不记得)中将自动处理其引用计数。 诀窍在于,在执行垃圾收集器之前,某些引用不会被释放。 这取决于 COM 对象实例化的内容。 例如,打开数据库游标的 COM 对象将使这些游标在内存中保持活动状态,直到释放这些游标上的引用计数。 通过 .NET/COM 互操作,直到垃圾收集器执行或者您使用 Marshal.ReleaseComObject(或 FinalReleaseComObject)显式释放引用时,才会释放引用。
我个人没有使用过 Microsoft Office PIA,但在大多数情况下,您不应该显式发布引用。 只有当您的应用程序开始锁定其他资源或崩溃时,您才应该开始怀疑悬空引用。
编辑:如果您遇到确实需要清理 COM/Interop 对象的情况,请使用 Marshal.FinalReleaseComObject - 它将引用计数一直归零,而不是仅减一 - 并设置对象引用为 null。 如果您确实想要安全,则可以显式强制垃圾回收 (GC.Collect),但要小心不要过于频繁地执行 GC,因为它确实会造成明显的性能损失。
PIAs are .NET interop wrappers. This means that in the object's destructor (or Dispose - I can't remember) will automatically handle its reference count. The trick is that some references won't be released until the garbage collector is executed. It depends on what the COM object instantiates. For instance, a COM object that opens database cursors will keep those cursors alive in memory until the reference count on those cursors is released. With the .NET/COM interop, the references aren't released until the garbage collector executes or you explicitly release the reference using Marshal.ReleaseComObject (or FinalReleaseComObject).
I personally haven't worked with the Microsoft Office PIAs, but under most circumstances, you shouldn't have to explicitly release the references. It is only when your application starts to lock other resources or crash that you should start being suspicious about dangling references.
EDIT: If you run into a situation where you do need to cleanup COM/Interop objects, use Marshal.FinalReleaseComObject - which takes the reference count all the way to zero instead of just decrementing by one - and set the object reference to null. You can explicitly force garbage collection (GC.Collect) if you really want to be safe, but be careful of doing GC too often as it does invoke a noticeable performance hit.
此处有一些使用托管包装器的良好实践..值得一试。 。
There are some good practices here using a managed wrapper..worth checking out..
也许这只是我的迷信,但我决定通过 Marshal.ReleaseComObject() 显式释放 Office PIA,因为当我的应用程序崩溃时,对 Excel 和 Word 的引用保持打开状态。 我没有深入探究原因(愚蠢的截止日期),但将它们作为班级处置模式的一部分发布解决了这个问题。
Maybe it's just my superstition, but I decided to explicitly release the Office PIA via Marshal.ReleaseComObject() because when my application crashed, the references to Excel and Word were staying open. I didn't dig too deep into why (stupid deadlines), but releasing them as part of my class's dispose pattern fixed that problem.
如果您希望 Office 应用程序的实例退出,则确实需要这样做,如 这篇文章。
除了最简单的情况之外,很难在所有情况下都做到正确。
You do need to do so if you want the instance of the Office application to exit, as described in this post.
And it's difficult to get it right in all but the most simple scenarios.
关于 .Net/COM 互操作有一个简单的规则 - 如有疑问,请始终使用 Release()。 :-)
There's one simple rule about .Net/COM interop - When in doubt, always Release(). :-)
我的经验表明您必须这样做,否则(至少 Outlook)应用程序可能根本不会关闭。
但这会打开另一个蠕虫罐,因为看起来 RCW 是每个进程的,因此您可以破坏其他一些插件,这些插件碰巧引用了同一对象。
我在此处发布了一个相关问题,但我仍然没有明确的答案。 一旦我了解更多,我将编辑这篇文章。
My experience shows that you have to, otherwise (at least Outlook) the application may not shut down at all.
But this opens another can of worms, as it looks like the RCWs are per process, thus you can break some other addin, which happens to have a reference to the same object.
I have posted a related question here, but I still have no clear answer. I'll edit this post once I know more.