0

My class is using a COM resource, and I have inherited it from IDisposable. and for cleaning the unmanaged resources I have that Dispose() method where I am calling a Marshall.ReleaseCOMObject() method ...So my question is do we still need a Destructor method ( Finalizer) too ? to release the COM resources? When I DO have the finalzier method and calling Marshal or Dispose in it, I will get a RCW error and when I REMOVE the finalizer method I won't get RCW error anymore But if I look at a memory profiler I can see the Unmanaged Resources memory keeps getting increased eveery time I open the form that has this COM resources in it...so looks likes it is not cleaning it up? So what's the correct way of cleaning up COM resources in a C# app?

I will update the question with some code sample that I have soon.

Thanks.

private MyCOMobject theCOMobject = null;

static SuppressFieldCntrlr()
{
    new SomeCalss();
}


private bool disposed = false;

public void Dispose()
{
    Dispose(true);
    GC.SuppressFinalize(this);
}

private void Dispose(bool disposing)
{
    if (!this.disposed)
    {
        if (disposing)
        {
           //nothing in here, is it just for Managed Resources? 
        }

        Marshal.ReleaseComObject(this);
        MethodFoo(false);

        disposed = true;
    }
}
Quintin Robinson
  • 81,193
  • 14
  • 123
  • 132
Bohn
  • 26,091
  • 61
  • 167
  • 254
  • 2
    Just wanted to add: If you add the finalizer in your class, your class will automatically handled a bit differently. The first swoop of the gc, your object is not directly collected, but put on the finalizer queue. And on the next run, will get called and collected. But of course this only happens if your object is not hold anymore by any reference, otherwise you might just have a plain memory leak, which i guess is your problem. – dowhilefor Nov 28 '12 at 17:20
  • @dowhilefor : intresting info. I didn't know bout the queue. Plain memory leak sounds about right. Can you please elaborate on how to fix and find it? here is the original question about this, not answred yet : http://stackoverflow.com/questions/13609098/writing-the-correct-idisposable-implementation-for-classes-with-com-objects/13609416#13609416 thanks – Bohn Nov 28 '12 at 17:23
  • 1
    Well my best advise is: Use a memory profiler to find the leak :) If prefere redgates ants memory profiler, but i'm sure there are a lot out there. A couple of suggestions for investigation: Remember that Events hold hard references. Check if you use singletons in fact, check all objects that at one point hold a reference and live longer than your leaking class. – dowhilefor Nov 28 '12 at 22:50
  • @dowhilefor : yep I have redgate...and the class constructor is STATIC... so it only gets called once...Smelly? – Bohn Nov 28 '12 at 23:17

3 Answers3

2

If your class doesn't directly own an unmanaged resource, and you know that no derived class will ever directly own an unmanaged resource (e.g. because your class is sealed, your class is internal), then you don't need a finalizer.

Personally I'd implement the standard pattern with a finalizer even if it's not strictly necessary. Mainly for the principle of least surprise, and because someone else may decide to unseal it or allow derived classes with an unmanaged resource in the future.

Note also that a COM object is a managed resource, so you should call ReleaseComObject when disposing is true:

private void Dispose(bool disposing)
{
    if (!this.disposed)
    {
        if (disposing)
        {
            // Dispose managed resources
            Marshal.ReleaseComObject(this);
        }
        // If you directly own unmanaged resources, they'd be freed here

        disposed = true;
    }
}
Joe
  • 122,218
  • 32
  • 205
  • 338
  • I would posit that if a class isn't expressly designed to deal with an unmanaged resource, no derived class should directly hold any either. Instead, if a derived class needs to own an unmanaged resource, that resource should be encapsulated within a small (possibly private) class that's designed to ensure its cleanup, and the derived class should store the resource in an object of that smaller class. The resource-holder object would need a finalizer, but the derived class would not. The .net `IDisposable` pattern exists to allow derived classes to do something *they shouldn't do anyway.* – supercat Nov 29 '12 at 16:02
2

You're encapsulating a managed object, not an unmanaged one. You haven't P/invoke'd to obtain a Win32 file handle, or a device context, or anything like that; rather, you've obtained a reference to a managed object - the RCW. You should put your call to Marshal.ReleaseComObject in the if (disposing) section of your Dispose(bool) method.

The RCW itself will have a finalizer which will take care of the IUnknown->Release() bookkeeping of the actual COM object, so if you haven't already called ReleaseComObject at a point where finalization needs to occur, the COM object will be deleted by the garbage collector.

prprcupofcoffee
  • 2,950
  • 16
  • 20
  • ok thanks, So shall I REMOVE the Finalizer method for now? will try it now and also will look at memory profiler results. My fear is the Unmanaged section keeps getting bigger and bigger without the finalizer. But Sure I will try it now). – Bohn Nov 28 '12 at 17:30
  • From what you've shown, your class doesn't have anything in it that needs finalizing, so I'd remove it. – prprcupofcoffee Nov 28 '12 at 17:32
0

If we have unmanaged resources, finalizer is strongly recommended. In this case:

~ClassName
{
    Dispose(false);
}
RavingDev
  • 2,817
  • 1
  • 17
  • 19
  • I was going to mention this but you said something about an exception. Is this what your finalizer looked like? – Alan Nov 28 '12 at 17:19
  • @Alan : Yes, it is exactly what I had at the beginning . The original question with that code which is not answered is here: http://stackoverflow.com/questions/13609098/writing-the-correct-idisposable-implementation-for-classes-with-com-objects/13609416#13609416 – Bohn Nov 28 '12 at 17:20