2011-07-18 50 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的事實! –