Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In what order should one release COM objects and garbage collect?

There are lots of questions on SO regarding the releasing COM objects and garbage collection but nothing I could find that address this question specifically.

When releasing COM objects (specifically Excel Interop in this case), in what order should I be releasing the reference and calling garbage collection?

In some places (such as here) I have seen this:

Marshall.FinalReleaseComObject(obj);
GC.Collect();
GC.WaitForPendingFinalizers();

And in others (such as here) this:

GC.Collect();
GC.WaitForPendingFinalizers();
Marshall.FinalReleaseComObject(obj);

Or doesn't it matter and I'm worrying about nothing?

like image 531
Sid Holland Avatar asked Nov 26 '12 19:11

Sid Holland


1 Answers

Marshal.FinalReleaseComObject() releases the underlying COM interface pointer.

GC.Collect() and GC.WaitForPendingFinalizers() causes the finalizer for a COM wrapper to be called, which calls FinalReleaseComObject().

So what makes no sense is to do it both ways. Pick one or the other.

The trouble with explicitly calling FinalReleaseComObject() is that it will only work when you call it for all the interface pointers. The Office program will keep running if you miss just one of them. That's very easy to do, especially the syntax sugar allowed in C# version 4 makes it likely. An expression like range = sheet.Cells[1, 1], very common in Excel interop code. There's a hidden Range interface reference there that you never explicitly store anywhere. So you can't release it either.

That's not a problem with GC.Collect(), it can see them. It is however not entirely without trouble either, it will only collect and run the finalizer when your program has no reference to the interface anymore. Which is definitely what's wrong with your second snippet. And which tends to go wrong when you debug your program, the debugger extends the lifetime of local object references to the end of the method. Also the time you look at Taskmgr and yell "die dammit!"

The usual advice for GC.Collect() applies here as well. Keep your program running and perform work. The normal thing happens, you'll trigger a garbage collection and that releases the COM wrappers as well. And the Office program will exit. It just doesn't happen instantly, it will happen eventually.

like image 163
Hans Passant Avatar answered Sep 18 '22 12:09

Hans Passant