2011-07-18 19 views
9

终结器总是被.net框架调用,所以序列可能失控;即使构造函数失败,析构函数仍然可以被触发。c#:如何处理来自第三方库的终结器异常?

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

例如,在下面的代码中,虽然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的终结,至少我可以做一些记录 - 我可以允许例外程序崩溃,去发现错误asap - 或者如果我想“容忍”这个异常,我可以尝试一个catch来压制这个异常,并且有一个优雅的退出。

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

我该怎么办?

+1

+1有趣的问题(与此同时,向提供'A'和'B'的图书馆供应商发出紧急的错误报告)。 – Ergwun

+0

^^ - 好点。需要成为一个真正的答案。 –

回答

2

听起来像第三方实用程序写得很差。 :)

您是否尝试过使用AppDomain.UnhandledException来捕捉它?

+0

是的,我现在正在这样做。它可以做日志记录,但是......不能优雅地退出...... – athos

0

您可能想为您的应用程序考虑全局异常处理程序。你没有指明如果你这样做ASP.NET,WinForm的,MVC等,但这里有一个控制台应用程序:

.NET Global exception handler in console application

在ASP.NET中,你可以使用Global.asax文件赶上未处理的例外。

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

只是一些想法要考虑。

0

您可以使用GC.SuppressFinalizer(objA)GC.KeepAlive(objA)将使用KeepAliveobjB的时候才会完成,因为objA“这是活着的”防止调用该对象的最终完成垃圾收集器,因此仍然有它的参考。但是如果您忘记以正确的方式完成或处理objA,则应该从知道内存泄漏

但假设objA在一种方法的例子某些点有初始化另一个objectB,并没有妥善处理它,那么很遗憾,我不件事你可以做任何事情。

您可以尝试的另一件事是检查该库在Release模式而不是Debug模式下的行为是否有所不同;例如,他们可能只在终结抛出异常,如果在调试模式下得到所谓“它种帮手给开发商,所以如果他们不叫处理或完成在正确的方式异常将抛出在调试对象”:

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

如果情况并非如此,那么我认为你会在与图书馆打交道的时候遇到困难。

+0

对不起约旦,我想我没有明确地提出我的问题,这样你可能会对它产生误解。 – athos

+0

@athos:对不起,我再次读你的问题,并发现我错过了'objA'为null的事实! –