当进程被终止时,如何清理C#中的非托管资源

8

我有一个类,可以实例化一个独立进程的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;
    }
}

我将其称为以下内容:

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

        //Do stuff

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

        Console.ReadLine();
    }

现在,当程序正常执行时,这会清理我的COM对象。但是,如果我在程序执行过程中关闭它,框架将永远不会调用释放我的非托管对象的代码。这很公平。但是,是否有一种方法可以强制程序即使被杀死也自我清理?

编辑:从任务管理器中进行强制终止看起来并不乐观 :(

2个回答

7
将其放在try finally或使用子句中,可以让你实现大部分功能:
using (MyComObject test = new MyComObject())
using (MyComObject test2 = new MyComObject()) {
    // do stuff
}
Console.ReadLine();

具体的应用程序如何关闭将决定您可以采取的任何其他措施(例如使用CriticalFinalizerObject)。

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

编辑:您还应该释放Com对象,直到返回值为<= 0


4

有一个最佳实践是使用 using 语句:

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

这基本上是将finally块放入到作用域的末尾自动调用dispose。每当您负责清理IDisposable实例时,应该使用using语句。但是,它不能解决整个进程突然中止的情况。虽然这种情况非常罕见,但您可能不想担心它。(很难避免)我原本期望您的终结器会与您之前的代码一起被调用。


那也不行。如果我在使用块的中间杀死进程,COM 服务器仍然会保持活动状态。 - Steve
你是如何终止进程的?你是否在处理块中放置了任何日志以查看发生了什么? - Jon Skeet
关闭程序时,只需使用正常的关闭方式即可。从任务管理器中终止程序可能会更加危险。如果您以“正常”的方式关闭程序,COM服务器是否能够正确关闭? - Jon Skeet
1
是的,如果我以正常方式关闭,一切都关闭得很好。但是从任务管理器或“小x”中关闭时,我的COM对象没有被清除。 - Steve
我也遇到了这个问题,即使使用块也是如此……非常令人沮丧。似乎对于控制台应用程序,按下“X”或Ctrl+C都会终止执行,而不考虑托管资源(例如我的连接……)。 - Walt W

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接