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);

我在这里不确定的是,如果我释放每个rrng然后我也释放rng我是否有效地释放rng了两次或正确地释放r了对rngrng本身的附加引用?

感谢您的建议!

编辑

我选择了后一种策略:

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);

这大大减少了内存......

再次 - 谢谢大家!

4

1 回答 1

5

不幸的是,有很多虚假信息四处流传。首先让我清楚地说明答案:

Marshal.ReleaseComObject大多数情况下,您不必打电话。为什么?因为垃圾收集器会为你做这件事。* 请注意,我说得最多,您可能会发现坚持许多参考文献会导致问题(无论出于何种原因)。仅在这些情况下,您是否决定致电Marshal.ReleaseComObject.

参考

Kristofer,我们一直为 COM 对象自动释放,因为 GC 确定它需要清理它们。它们不会立即被清理,但会在一两次 GC 之后的某个时间点被清理。我已经与团队确认了这一点。

他们说:

在博客中的应用程序类型中并不重要,如果人们搞砸了他们的应用程序将会失败并且他们会得到明显的引用计数错误。如果他们的代码是在办公室内加载的,而不是相反,这更令人担忧,因为您最终可能会发布其他人的参考,然后可能会出现他们在代码中没有注意到但破坏某人的问题else 的 office 加载项。

所以,关键是虽然 ReleaseComObject 更具确定性,但通常没有必要,因为 GC 会做同样的事情。

另外,我建议您阅读Marshal.ReleaseComObject Considered Dangerous

如果您想调用“Marshal.ReleaseComObject”,您能否 100% 确定没有其他托管代码仍然可以访问 RCW?如果答案是“不”,那就不要打电话。最安全(也是最明智)的建议是完全避免 Marshal.ReleaseComObject 出现在组件可以随着时间的推移重用和版本化的系统中。

现在,也许有某些原因您需要确定性地释放这些 COM 对象,但在大多数情况下,您可以删除所有这些Marshal.ReleaseComObject调用。

于 2015-04-30T04:10:12.490 回答