假设我有一个COM对象(非托管)和.NET客户端。
在释放COM对象时,是否需要从.NET客户端调用Marshal.FinalReleaseComObject
方法?
假设我有一个COM对象(非托管)和.NET客户端。
在释放COM对象时,是否需要从.NET客户端调用Marshal.FinalReleaseComObject
方法?
using
语句调用它。) - user166390GC.Collect + GC.WaitForPendingFinalizers
不起作用,但FinalReleaseComObject
起作用,那么很有可能你的程序中的某个地方,FinalReleaseComObject
未释放对COM对象的托管引用。 - JaredParusing
vs.希望Stream finalizer运行没有什么区别。有时它只是在应该运行时没有运行。再加上缓存(在OOM中臭名昭著),这只会“使事情不能正常工作”。 - user166390一个经过修改的"是"和一个"否"。
首先,要记住 ReleaseComObject
并不会自动减少真实的COM对象引用计数。相反,它会减少内部RCW计数器。(每次将相同的COM对象从COM->NET移动时,它将使用相同的RCW并将RCW计数器增加一次。)同样,FinalRelaseComObject
也会影响RCW计数器,并有效地将其设置为0。当RCW计数器变为零时,.NET将减少实际的COM引用计数。
所以,"是",但是根据以下规则进行修改:
ReleaseComObject
,但不应调用 FinalReleaseComObject
。也就是说,每次对象越界时都应该被调用一次,即使它导致引用等于RCW。我提到了上述规则,而不是 FinalReleaseComObject
,因为RCW对象被缓存在标识代理中,所以 使用 FinalReleaseComObject
将会影响您甚至不知道的COM->NET边界越界!(这很糟糕,在这一点上,我完全同意JaredPars的答案。)
而且 "否" 是指当一个RCW被回收时(调用终结器),它将自动“释放”COM引用(实际上在自身上调用FinalReleaseComObject
)。请记住,由于只有一个RCW对象,这意味着只要.NET中存在对它的引用,它就永远不会被回收。如果RCW被回收,则没有问题,因为根据上述情况,没有对该RCW的更多引用,因此.NET知道可以将COM引用计数减少一次(可能会导致销毁COM对象)。