释放 Excel 个 COM 对象

Releasing Excel COM objects

我有一些使用 Excel COM 对象的 Excel 自动化代码。从 other SO posts 我知道应该执行以下操作以尽早释放对象:

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 我是否有效地释放了 rng 两次或正确释放对 rngrng 本身的附加引用 r ?

提前致谢!

编辑

我选择了后一种策略:

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

显着减少了内存...

再次感谢大家!

不幸的是,到处都是很多虚假信息。 先把答案说清楚:

大多数 情况下,您不必致电 Marshal.ReleaseComObject。为什么?因为垃圾收集器会为你做这件事。 * 请注意,我说的是 most,您可能会发现保留许多引用会导致问题(无论出于何种原因)。仅在这些情况下,您是否应该决定调用 Marshal.ReleaseComObject.

Reference:

Kristofer, we’ve always had automatic releases for COM objects as the GC determines it needs to clean them up. They don’t get cleaned up immediately, but do get cleaned up at some point later after a GC or two. I've confirmed with this with the team.

They said:

In the type of app in the blog it doesn’t really matter, if people screw up their app will fail and they’ll get obvious ref-counting bugs. In cases where their code is being loaded inside of office, rather than the other way around, it is much more concerning because you can end up releasing someone else’s reference then there can be problems that they don’t notice in their code but breaks someone elses office add-in instead.

So, the point is that while ReleaseComObject is more deterministic, it's usually not necessary as the GC will do the same thing.

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

If you’re tempted to call “Marshal.ReleaseComObject”, can you be 100% certain that no other managed code still has access to the RCW? If the answer is ‘no’, then don’t call it. The safest (and sanest) advice is to avoid Marshal.ReleaseComObject entirely in a system where components can be re-used and versioned over time.

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