释放Excel COM对象

3
我有一些使用Excel COM对象的Excel自动化代码。从其他SO帖子中,我知道应该尽早采取以下措施释放对象:
Excel.Range rng = GetSomeRange();

// do something with rng...

Marshal.ReleaseComObject(rng);

然而,如果我要循环遍历一个范围内的单元格,以下是否是正确的步骤?

Excel.Range rng = GetSomeRange();
foreach (Excel.Range r in rng)
{
    // do something with r
    Marshal.ReleaseComObject(r); // release at earliest possible convenience
}

Marshal.ReleaseComObject(rng);

我在这里不确定的是,如果我释放rng中的每个r,然后再释放rng,我是在正确地释放对rngr的引用,还是相当于释放了两次rng

提前感谢!

编辑

我采取了后一种策略:

Excel.Range rng = GetSomeRange();
foreach (Excel.Range r in rng)
{
    // do something with r
    Marshal.ReleaseComObject(r); // release at earliest possible convenience
}

Marshal.ReleaseComObject(rng);

由于某些优化,它显著地减少了内存占用...

再次感谢大家!


1
你可能不需要显式释放像 r 这样的小型 COM 对象。请参考这个答案 https://dev59.com/33VC5IYBdhLWcg3w4VNy#159419。 - Eric J.
1个回答

5

很不幸,有许多虚假信息在流传。 首先,让我清晰地说明答案:

在大多数情况下,您不需要调用Marshal.ReleaseComObject。为什么?因为垃圾回收器会替你完成这项工作。 *请注意,我说的是“大多数情况”,您可能会发现保留太多引用会导致问题(出于任何原因)。在这些情况下,只有当您决定调用Marshal.ReleaseComObject时才应该这样做。

参考

Kristofer,我们一直有自动释放COM对象的机制,因为GC决定需要清理它们。它们不会立即被清理,但在经过一两次GC后会被清理。我已经与团队确认了这一点。
他们说:
在博客中介绍的应用程序类型中,这并不重要,如果人们搞砸了,他们的应用程序将失败,并且他们会遇到明显的引用计数错误。如果他们的代码被加载到Office内部,而不是反之,则情况会更加令人担忧,因为您可能会释放其他人的引用,然后可能会出现问题,他们在其代码中没有注意到,但会破坏其他人的Office插件。
因此,关键是虽然ReleaseComObject更具确定性,但通常不必要,因为GC将执行相同的操作。
另外,我建议您阅读Marshal.ReleaseComObject Considered Dangerous。
(保留html标签)
如果你想调用“Marshal.ReleaseComObject”,你能百分之百确定没有其他托管代码仍在访问RCW吗?如果答案是否定的,那就不要调用它。在一个组件可以被重复使用和随时间版本化的系统中,避免使用Marshal.ReleaseComObject是最安全(和最理智)的建议。现在,也许有一些原因需要确定性地释放这些COM对象,但在大多数情况下,可以删除所有这些“Marshal.ReleaseComObject”调用。

非常好的答案,谢谢@Jesse。在我的系统中,我每隔几秒钟就会创建“Range”对象,并且这些数字会在会话中增加到约100,000个。因此,(我怀疑)我看到的Excel内存占用有时会高达800Mb,这在我看来是不正确的。对于“ReleaseComObject”,我仅在确定不再需要我的对象时使用它。例如,在作用域中使用并且一旦超出作用域就不再需要。是否可能创建如此大量的对象会导致像我描述的大规模“泄漏”?再次感谢! - Pat Mustard
@PatMustard:如果您正在创建这么多Range对象,可能是因为内存使用量的原因。您创建这么多的原因是什么?例如,一次性读取/更新会更好。此外,您还可以尝试使用GC.Collect(),但我建议将其作为最后的手段。 - Jesse Good
很不幸,我需要这样做,因为我的表格需要足够强大的鲁棒性来处理运行时范围的更改以响应变化的值等。我已经实现了后一种策略(释放引用组件rrng本身),并且我看到了内存消耗的显着改善。该表格与实时数据有关,因此我真的不想走GC路线。总的来说,现在情况好多了 - 感谢您的建议...它帮了我很多 :) - Pat Mustard

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接