c#:如何处理来自第三方库的终结者例外?

时间:2011-07-18 01:50:01

标签: c# exception finalizer

终结器总是被.net框架调用,因此序列可能会失控;即使构造函数失败,仍然可以触发析构函数。

当这样的终结者例外来自第三方库时,这可能带来麻烦:我找不到处理它们的方法!

例如,在下面的代码中,尽管A类的构造函数总是抛出异常而失败,但是A的终结符将由.net框架触发,同时~B()被调用为A具有B类型的属性。

class Program // my code
{
    static void Main(string[] args)
    {
        A objA;
        try
        {
            objA = new A();
        }
        catch (Exception)
        {
        }

        ; // when A() throws an exception, objA is null

        GC.Collect(); // however, this can force ~A() and ~B() to be called.

        Console.ReadLine();
    }
}

public class A  // 3rd-party code
{
    public B objB;

    public A()
    {
        objB = new B(); // this will lead ~B() to be called.
        throw new Exception("Exception in A()");
    }

    ~A() // called by .net framework
    {
        throw new Exception("Exception in ~A()"); // bad coding but I can't modify
    } 
}

public class B // 3rd-party code
{
    public B() { }

    ~B() // called by .net framework
    {
        throw new Exception("Exception in ~B()"); // bad coding but I can't modify
    } 
}

如果这些是我的代码,那就更容易了   - 我可以在终结器中使用try-catch,至少我可以做一些日志记录   - 我可以允许异常崩溃程序,尽快发现错误   - 或者如果我想“容忍”异常,我可以使用try-catch来抑制异常,并且有一个优雅的退出。

但如果A和B是来自第三方库的课程,我什么也做不了! 我无法控制异常发生,我无法捕捉它们,所以我无法记录或压制它!

我该怎么办?

3 个答案:

答案 0 :(得分:2)

听起来第三方实用程序编写得很糟糕。 :)

您是否尝试使用AppDomain.UnhandledException捕获它?

答案 1 :(得分:0)

您可能需要考虑应用程序的全局异常处理程序。你没有说明你是在做ASP.NET,WinForm,MVC等,但是这里有一个用于控制台应用程序:

.NET Global exception handler in console application

在ASP.NET中,您可以使用Global.asax文件来捕获未处理的异常。

如果您总是在应用程序中调用GC.Collect(),您也可以尝试将其包装在try-catch块中。

只需考虑一些想法。

答案 2 :(得分:0)

您可以使用GC.SuppressFinalizer(objA)GC.KeepAlive(objA)来阻止垃圾收集器调用该对象的finalize,因此在使用KeepAlive时,objB将无法完成,因为objA“活着的”仍然有参考。但是,如果您忘记以适当的方式完成或处置objA,那么您应该知道内存泄漏

但是假设某个方法中某个点的objA已初始化另一个objectB并且它没有正确处理它,那么不幸的是我不能做任何关于它的事情。

您可以尝试的另一件事是检查当您处于Release模式而不是Debug模式时,该库的行为是否不同;例如,如果在调试模式中调用它们,它们可能只会在终结器中抛出异常“它对开发人员来说是一种帮助,所以如果他们不调用dispose或以正确的方式完成对象,则会在调试时抛出异常”:

~A()
{
#if DEBUG
    throw new Exception("Exception in ~A()");
#endif//DEBUG
} 

如果情况并非如此,那么我认为你在处理这个图书馆的日子会很糟糕。