3

I have some Excel automation code that uses Excel COM objects. From other SO posts I know that one should do the following to release objects at the earliest convenience:

Excel.Range rng = GetSomeRange();

// do something with rng...

Marshal.ReleaseComObject(rng);

However, if I loop through cells in a range, is the following the correct procedure?

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

What I'm unsure of here is that if I release each r in rng and then I also release rng am I effectively releasing rng twice or correctly releasing additional references r to rng and rng itself ?

Thanks in adv.!

EDIT

I went for the latter strategy:

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

which has reduced the memory significantly...

again - thanks to all!

Community
  • 1
  • 1
Pat Mustard
  • 1,852
  • 9
  • 31
  • 58
  • 1
    You probably don't need to explicitly release the minor COM objects like `r`. See this answer http://stackoverflow.com/a/159419/141172 – Eric J. Apr 30 '15 at 03:56

1 Answers1

5

Unfortunately, there is a lot of false information floating around. First let me state the answer clearly:

You do not have to call Marshal.ReleaseComObject in most cases. Why? Because the Garbage Collector will do it for you. * Note that I said most, you may find that holding onto to many references causes problems (for whatever reason). In those cases only, should you decide to call 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.

Also, I suggest you read 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.

Now, maybe there is some reason you need to deterministically release those COM objects, but in most cases you can remove all those Marshal.ReleaseComObject calls.

Jesse Good
  • 50,901
  • 14
  • 124
  • 166
  • Great Answer, thanks, @Jesse. In my system I create `Range` objects every couple of seconds and these number up to ~100,000 over a session. As a cansequence, (I suspect) I see an Excel memory footprint that is at times upward of 800Mb which can't be right IMO. For `ReleaseComObject`, I only use this when I am certain that my objects are no longer needed. For example, when used in scope and are no longer required once out of scope. Is it possible that such large numbers of objects created would lead to large scale 'leaks' such as I have described? Thx again! – Pat Mustard Apr 30 '15 at 05:02
  • @PatMustard: If you are creating that many `Range` objects it is possible the memory usage is because of that. Is there a reason you are creating that many? For example, it would be better to read/update in one go. Also, you could also experiment with `GC.Collect()`, but I would leave that as a last resort. – Jesse Good Apr 30 '15 at 08:22
  • Unfortunately I need to do it like this since my sheet needs to be robust enough to handle runtime changes to ranges to respond to changing values etc. I've implemented the latter strategy (releasing the reference components `r` and the also `rng` itself and I see a significant improvement in memory consumption). The sheet is related to real time tick data so I don't really want to go down the GC route. All in all, things are much improved now - thanks for your advice... it's helped alot :) – Pat Mustard Apr 30 '15 at 08:27