tags:

views:

1136

answers:

2

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 :(

+5  A: 

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..

Jon Skeet
that doesn't work either. The COM servers stay alive if I kill the process in the middle of the using block.
Steve
How are you killing the process? Have you put any logging in your dispose blocks to see what's going on?
Jon Skeet
(Just closing the program with a normal shutdown should be fine. Terminating it from Task Manager is likely to be nastier.) Does the COM server shut down properly if you close the program in a "normal" way?
Jon Skeet
yes, everything shuts down fine if I do it in the normal way. From the task manager or the "little x", my COM objects are not cleaned up.
Steve
I'm actually having this problem as well, even with using blocks . . . quite frustrating. It appears that for console applications, pressing "X" or Ctrl+C'ing both terminate execution without regard to managed resources (I.E. connections in my case...)
Walt W
+5  A: 

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.

Mark Brackett