为什么使用FinalReleaseComObject而不是ReleaseComObject? [英] Why use FinalReleaseComObject instead of ReleaseComObject?

查看:2316
本文介绍了为什么使用FinalReleaseComObject而不是ReleaseComObject?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道基本的区别,因为 ReleaseComObject 只是减少一个计数器一个和 FinalReleaseComObject 减少到零。

I know the basic difference as ReleaseComObject only decreases some counter by one and FinalReleaseComObject decreases it to zero.

所以我通常听到的是,调用 FinalReleaseComObject ,因为然后你确定COM对象是真正释放。

So what I usually hear is, call FinalReleaseComObject because then you are sure that the COM object is really released.

但这让我想知道,这个计数器有点对吗?如果你总是调用 FinalReleaseComObject ,你不会打破这个机制。如果在调用 ReleaseComObject 之前该计数器不是一个,那么是否可能有原因?

But this makes me wonder, there is a point to this counter right? Aren't you breaking that mechanism if you always call FinalReleaseComObject. If that counter is not one before you call ReleaseComObject, is there not probably a reason for it?

当它不应该是高于一个时,会是什么?

What could cause it to be higher than one when it should not be?

提前感谢。

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

PS: My COM experience only consists of using Excel Interop. Not sure if this question is local to that domain (i.e. outside Office Interop, FinalReleaseComObject is not often used).

文章 Dan提到,当你完成后,谈到使用 ReleaseComObject 。根据文章中的说明,这是正常方式。我认为,如果你这样做这一贯,它应该工作正常。在对文章的评论中,作者建议有人在循环中调用 ReleaseComObject ,直到它被真正释放为止( article 是从2006年开始的,所以这是类似于调用 FinalReleaseComObject )。但他也说这可能是危险的。

The article Dan mentioned talks about using ReleaseComObject when you're done. As I understand from the article, this is the normal way. I think that if you do this consistently it should work fine. In a comment to the article the author suggests someone to call ReleaseComObject in a loop until it is really released (the article is from 2006, so this is analogues to calling FinalReleaseComObject). But he also states that this could be dangerous.


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

If you really want to the RCW to call Release() at a particular point in the code, you can call ReleaseComObject() in a loop until the return value reaches zero. This should ensure the RCW will call Release(). However, if you do that, be warned, when the other managed references try to use that RCW, it will cause an exception."

这导致我相信,总是调用 FinalReleaseComObject 是一个好主意,因为你可能会导致异常在其他地方。现在,你应该只调用这个,如果你绝对确定你可以。

This leads me to believe that it is indeed not a good idea to always call FinalReleaseComObject, as you can cause exceptions elsewhere. As I see it now, you should only call this if you are absolutely sure that you can.

然而,我没有这方面的经验,我不知道我可以如果是这样,那么我会说 FinalReleaseComObject 更多的是一个hack比一个最佳做法。

Still, I have little experience in this matter. I don't know how I can be sure. If the counter is increased when it should not be, is it not better to fix that problem? If so, then I would say FinalReleaseComObject is more of a hack than a best practice.

推荐答案

一些前导...

可调用包装器(RCW)只在其包装的非托管COM接口上调用IUnknown.AddRef,但是,RCW还维护一个单独的计数,用于管理引用的数量,它与RCW本身有关,这是通过调用Marshal.ReleaseComObject减少。当托管引用的计数达到零时,RCW在非托管COM接口上调用IUnknown.Release一次。

A Runtime Callable Wrapper (RCW) only calls IUnknown.AddRef once on the unmanaged COM interface that it wraps. However, an RCW also maintains a separate count of the number of managed references there are to the RCW itself. It is this separate count of managed references that is decremented by a call to Marshal.ReleaseComObject. When the count of managed references reaches zero, the RCW calls IUnknown.Release once on the unmanaged COM interface.

Marshal.FinalReleaseComObject通过一次调用使托管引用计数为零,因此立即调用包装的非托管IUnknown.Release方法(假设托管引用计数不是已经为零)。

Marshal.FinalReleaseComObject takes the managed reference count to zero with a single call, and thus invokes the wrapped unmanaged IUnknown.Release method immediately (assuming that the managed reference count was not already zero).

那么为什么要同时使用Marshal.ReleaseComObject和Marshal.FinalReleaseComObject?调用Marshal.FinalReleaseComObject只是避免必须写入一个循环,它会重复调用Marshal.ReleaseComObject,直到它返回0,当您希望指示真正使用COM对象现在

So why have both Marshal.ReleaseComObject and Marshal.FinalReleaseComObject? Calling Marshal.FinalReleaseComObject simply avoids having to write a loop that calls Marshal.ReleaseComObject repeatedly until it returns 0 when you wish to indicate that you've really finished using a COM object now.

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

Why use either Marshal.ReleaseComObject or Marshal.FinalReleaseComObject? There are two reasons I'm aware of:

第一个是确保被封装的COM对象使用的非托管资源(如文件句柄,内存等)作为对非托管IUnknown.Release()方法的调用的结果,尽快释放。

The first is to ensure that unmanaged resources (such as file handles, memory etc.) being used by the wrapped COM object are freed as soon as possible as a result of the resulting call to the unmanaged IUnknown.Release() method.

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

The second is to ensure that the thread calling the unmanaged IUnknown.Release() method is under your control, and not the finalizer thread.

在没有调用任何一个Marshal方法的情况下,RCW的终结器将在RCW被垃圾回收之后最终调用非管理的IUnknown.Release()方法。

Without calls to either of these Marshal methods, the RCW's finalizer will eventually call the unmanaged IUnknown.Release() method some time after the RCW has been garbage collected.

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

For corroborative details, see the Visual C++ Team blog entry Mixing deterministic and non-deterministic cleanup

这篇关于为什么使用FinalReleaseComObject而不是ReleaseComObject?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆