Memory CLR是否从COM对象释放内存?

Memory CLR是否从COM对象释放内存?,memory,com,clr,Memory,Com,Clr,我正在使用Outlook加载项,在那里我创建了许多COM对象(Outlook邮件、Outlook文件夹等)。我的理解是,由于这些对象是COM对象,CLR不会从这些对象中释放内存,我必须负责从这些对象中释放内存 Marshal.ReleaseComObject(对象) 但不幸的是,这似乎不起作用;这是有效的。在那之后,我没有得到任何与记忆相关的异常。 我的问题是,如果CLR可以从COM对象释放内存,为什么它自己不这样做呢。如果不能,那么在我的例子中GC.Collect()语句是如何工作的。您是否尝

我正在使用Outlook加载项,在那里我创建了许多COM对象(Outlook邮件、Outlook文件夹等)。我的理解是,由于这些对象是COM对象,CLR不会从这些对象中释放内存,我必须负责从这些对象中释放内存

Marshal.ReleaseComObject(对象)

但不幸的是,这似乎不起作用;这是有效的。在那之后,我没有得到任何与记忆相关的异常。
我的问题是,如果CLR可以从COM对象释放内存,为什么它自己不这样做呢。如果不能,那么在我的例子中GC.Collect()语句是如何工作的。

您是否尝试在Marshal.ReleaseComObject之后分配内存?因为,您知道,垃圾收集器将按自己的意愿运行,这意味着通常在分配内存时,而不仅仅是在您认为它应该运行时(当然,除非您调用GC.Collect)


到目前为止,我在自动释放COM对象方面没有遇到任何问题,只有当我希望COM服务器立即关闭时,我才调用了Marshal.ReleaseComObject。

是否尝试在Marshal.ReleaseComObject之后分配内存?因为,您知道,垃圾收集器将按自己的意愿运行,这意味着通常在分配内存时,而不仅仅是在您认为它应该运行时(当然,除非您调用GC.Collect)


到目前为止,我在自动释放COM对象方面没有遇到任何问题,只有当我希望COM服务器立即关闭时,我才调用Marshal.ReleaseComObject。

要将COM与.Net一起使用,您需要很好地理解。基本上,.Net代码中引用COM对象的所有内容实际上都是对RCW的引用。RCW通过计算对基础COM对象的引用数量来管理基础COM对象上的引用计数,当基础COM对象上的引用计数降至0时,它将调用基础对象上的
Release
(一次)。当RCW处于活动状态时,它将在COM对象上维护一个引用

ReleaseComObject
API将把RCW上的引用计数减少1。如果这使RCW上的引用计数为0,则RCW将调用COM对象上的
Release
,否则不会。还有一个
FinalReleaseComObject
,它将导致RCW上的引用计数变为0(从而导致RCW调用
Release
),尽管如果RCW上还有其他未完成的引用,这有点危险,因为它们可能会出错

“正常情况下”,RCW上的引用是在具有引用的对象被垃圾收集时进行管理的——这可以解释为什么在强制垃圾收集时看到COM对象被释放。这一点,再加上我们对RCW工作原理的了解,告诉我们RCW上还有其他引用,您也“需要”调用
ReleaseComObject
,以使其
释放

调用
ReleaseComObject
是.Net运行时的一种结束运行,您必须非常小心地管理创建的所有引用。创建的一些引用是“隐式”引用——这些引用是因为执行了诸如调用属性之类的操作,这些属性返回引用,然后调用这些引用。这有时被称为“太多点”问题,当您执行以下操作时:

object.foo.blah.baz.something()

“foo”、“blah”和“baz”可能都是对某个COM对象的引用,您需要考虑这些对象。

为了将COM与.Net一起使用,您需要对COM有很好的了解。基本上,.Net代码中引用COM对象的所有内容实际上都是对RCW的引用。RCW通过计算对基础COM对象的引用数量来管理基础COM对象上的引用计数,当基础COM对象上的引用计数降至0时,它将调用基础对象上的
Release
(一次)。当RCW处于活动状态时,它将在COM对象上维护一个引用

ReleaseComObject
API将把RCW上的引用计数减少1。如果这使RCW上的引用计数为0,则RCW将调用COM对象上的
Release
,否则不会。还有一个
FinalReleaseComObject
,它将导致RCW上的引用计数变为0(从而导致RCW调用
Release
),尽管如果RCW上还有其他未完成的引用,这有点危险,因为它们可能会出错

“正常情况下”,RCW上的引用是在具有引用的对象被垃圾收集时进行管理的——这可以解释为什么在强制垃圾收集时看到COM对象被释放。这一点,再加上我们对RCW工作原理的了解,告诉我们RCW上还有其他引用,您也“需要”调用
ReleaseComObject
,以使其
释放

调用
ReleaseComObject
是.Net运行时的一种结束运行,您必须非常小心地管理创建的所有引用。创建的一些引用是“隐式”引用——这些引用是因为执行了诸如调用属性之类的操作,这些属性返回引用,然后调用这些引用。这有时被称为“太多点”问题,当您执行以下操作时:

object.foo.blah.baz.something()

“foo”、“blah”和“baz”可能都是对某个COM对象的引用,你需要考虑一下。

现在我想起来为什么我不喜欢COM.Ha了。来自COM,这个蹩脚的.Net实现是不喜欢.Net的原因!有时候,我真的希望我能否决评论,但是,嘿,我用否决另一条来补偿:)现在我记得为什么我不这么做了