进程被终止时,C#清理非托管资源

Ste*_*eve 8 c# dispose

我有一个类来实例化一个COM exe进程.这堂课是

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我把它称之为如下

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

        //Do stuff

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

        Console.ReadLine();
    }
Run Code Online (Sandbox Code Playgroud)

现在,这会在程序正常执行时清理我的COM对象.但是,如果我在执行过程中关闭程序,框架就不会调用释放我的非托管对象的代码.这是公平的.但是,有没有办法迫使程序自行清理,即使它被杀死了?

编辑:从任务管理员的硬杀,它看起来并不乐观:(

Mar*_*ett 8

在最后尝试或使用子句包装它将使你在那里的大部分方式:

using (MyComObject test = new MyComObject())
using (MyComObject test2 = new MyComObject()) {
    // do stuff
}
Console.ReadLine();
Run Code Online (Sandbox Code Playgroud)

但是,关闭应用程序的具体细节将决定您可以执行的任何其他措施(例如使用CriticalFinalizerObject).

认为关闭的控制台应用程序(从小x开始)与Ctrl-C相同 - 在这种情况下,您可以订阅Console.CancelKeyPress.

编辑:您还应该使用ReleaseComObject,直到它返回<= 0.


Jon*_*eet 5

嗯,最好的做法是使用using语句:

using (MyComObject test = new MyComObject())
using (MyComObject test2 = new MyComObject())
{
    //Do stuff
}
Run Code Online (Sandbox Code Playgroud)

这实际上是finally在块的末尾自动调用块来调用dispose.你应该有using语句几乎只要你有你承担清理责任IDisposable的实例.但是,它并不能解决您的整个过程突然中止的情况.这是非常罕见的,你可能不想担心它.(这很难绕过它.)我已经预料到你的终结器会被你以前的代码调用,但是...