27

When should I use Marshal.FinalReleaseComObject vs Marshal.ReleaseComObject?

Is there any danger in using Marshal.FinalReleaseComObject?

Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
C. Ross
  • 31,137
  • 42
  • 147
  • 238

1 Answers1

29

There's some virtue in FinalReleaseComObject, it will crash your program quicker. "COM object that has been separated from its underlying RCW cannot be used" is the CLR telling you that you taking care of COM reference counts yourself instead of leaving it up the CLR was a mistake. Your mileage may vary, you cannot really trust to get it right when it works on your dev machine. Make sure you implement good error reporting when you deploy the code to your customer's machine.

The virtue is that there's only one place in your code where you got it wrong, the FinalReleaseComObject call. It gets much fuzzier when you use ReleaseComObject. Because that will go undetected for a while, crashing your program when the CLR calls the final IUnknown::Release(), the one that destroys the object. Very far removed from an incorrect ReleaseComObject call. But that's the doomsday scenario, the more likely outcome is that the call just doesn't make any difference because you missed the hard ones. Like mumble["foo"], an indexer reference that is so very hard to see being used.

Well, my advice is obvious: don't do this. You are competing with a machine that never gets it wrong. It is merely a bit slow at doing so. A very good "report from real life" is available here. The "silent assassin" section is most relevant.

If it is absolutely essential to get a COM server to exit instantly then let the machine take care of getting all the reference counts to 0. You do so with GC.Collect(). But do keep in mind that you have to place that call correctly if you want this to also work when you debug. It won't work in the same method that uses the COM objects, explained in this answer. Put it in the calling method instead.

Michael Bikovitsky
  • 903
  • 2
  • 10
  • 20
Hans Passant
  • 922,412
  • 146
  • 1,693
  • 2,536
  • 2
    Are you suggesting not releasing the object at all? – C. Ross Oct 14 '10 at 23:11
  • 2
    Yes. Why do you think you have to? – Hans Passant Oct 14 '10 at 23:13
  • 1
    Our vendor specified in their documentation that you had to release all objects after using them. – C. Ross Oct 14 '10 at 23:24
  • 3
    Well, maybe that wasn't so clear. Remove all the Marshal class calls. Come back when you notice any difference at all. – Hans Passant Oct 14 '10 at 23:58
  • 5
    I removed all my Marshal class calls and I found the code was much more stable, less RCW and COM errors. +1 Thanks!! I only had them in because the SAP SDK I'm working with said to put 'em in ... – Booji Boy Jan 21 '12 at 05:23
  • 3
    @HansPassant does advice (not tu use FinalReleaseCOM) also apply in the situation you are PInvoking unmanaged code? – probably at the beach May 30 '12 at 13:06
  • 3
    No, pinvoke has nothing to do with calling COM interface methods. Pinvoke is done with a [DllImport] attribute, there is no COM interface pointer associated with it. – Hans Passant May 30 '12 at 13:09
  • 1
    What if the COM object has a destructor that access some shared state that is also used from the constructor in a non-threadsafe manner? It seems that by relying on .Net's finalizer to do the release, you are now using the COM component in multi-threaded scenario. – Oskar Berggren Jan 21 '13 at 15:52
  • 1
    No, the finalizer marshals to the correct thread as required by the object's COM threading model (aka "apartment"). Threading is very different in COM, it is not left up to the app code like it is in .NET – Hans Passant Jan 21 '13 at 16:24
  • 1
    Can that model break (be abused) somehow? Because I'm seeing clear indications that indeterministic finalization happening after having forced a garbage collection triggers weird ComExceptions and Access Violations when the same code runs again to create new COM objects. If I apply WaitForPendingFinalizers() or remove the forced GC and instead call FinalReleaseComObject(), these problems doesn't show on consecutive runs. – Oskar Berggren Jan 21 '13 at 16:34