Steve
Steve

Reputation: 12054

C# cleanup unmanaged resources when process is killed

I have a class that instantiates a COM exe out of process. The class is

public class MyComObject:IDisposable
{
    private bool disposed = false;
    MyMath test;

    public MyComObject()
    {
        test = new MyMath();
    }

    ~MyComObject()
    {
        Dispose(false);
    }

    public double GetRandomID()
    {
        if (test != null)
            return test.RandomID();
        else
            return -1;
    }

    public void Dispose()
    {
        Dispose(true);

        GC.SuppressFinalize(this);
    }

    private void Dispose(bool disposing)
    {
       if (test != null)
       {
           Marshal.ReleaseComObject(test);
           test = null;
       }

       disposed = true;
    }
}

and I call it as follows

static void Main(string[] args)
    {
        MyComObject test = new MyComObject();
        MyComObject test2 = new MyComObject();

        //Do stuff

        test.Dispose();
        test2.Dispose();

        Console.ReadLine();
    }

now, this cleans up my COM object when the program executes normally. However, if I close the program in the middle of its execution, the framework doesn't ever call the code that releases my unmanaged object. Which is fair enough. However, is there a way to force the program to clean itself up even though its been killed?

EDIT: it doesn't look promising from a hard kill from the taskmanager :(

Upvotes: 8

Views: 6479

Answers (2)

Mark Brackett
Mark Brackett

Reputation: 85685

Wrapping it in a try finally or using clause will get you most of the way there:

using (MyComObject test = new MyComObject())
using (MyComObject test2 = new MyComObject()) {
    // do stuff
}
Console.ReadLine();

The specifics of how your app is being shutdown, though, will dictate any other measures you can do (like using CriticalFinalizerObject).

I think that a console app that gets closed (from the little x) is the same as a Ctrl-C - in which case you can subscribe to Console.CancelKeyPress for that.

Edit: You should also ReleaseComObject until it returns <= 0.

Upvotes: 7

Jon Skeet
Jon Skeet

Reputation: 1504122

Well, one best practice is to use using statements:

using (MyComObject test = new MyComObject())
using (MyComObject test2 = new MyComObject())
{
    //Do stuff
}

That essentially puts finally blocks in to call dispose automatically at the end of the scope. You should have using statements pretty much whenever you have an instance of IDisposable that you take responsibility for cleaning up. However, it doesn't fix the situation where your whole process is aborted abruptly. That's pretty rare though, and you may not want to worry about it. (It's pretty hard to get round it.) I'd have expected your finalizer to be called with your previous code though..

Upvotes: 4

Related Questions