2015-06-15 23 views
2

我正在使用蹩腳的第三方庫,因爲不幸的是我沒有選擇。當我調用它時,這個庫會在內部創建一堆線程,偶爾會在這些線程中的一個線程上拋出NullReferenceException異常。有沒有什麼辦法可以讓我捕捉到這些例外,即使我不擁有引發它們的線程?我無法更改第三方代碼。任何方式來捕捉我不擁有的線程上發生的異常?

舉一個簡單的例子來說明這個問題:

public static void main() 
{ 
    try 
    { 
     var crappyLib = new CrappyLibrary(); 
     crappyLib.DoCrappyThings(); 
    } 
    catch 
    { 
     Console.WriteLine("This never happens"); 
    } 
} 

// I do not own the following code, I can't change it 
public class CrappyLibrary 
{ 
    public void DoCrappyThings() 
    { 
     var t = new Thread(DoWork); 
     t.Start(); 
    } 
    private void DoWork() 
    { 
     throw new ThisLibrarySucksException(); 
    } 
} 
+0

您是否可以在您使用的第三方代碼周圍使用'try ... catch'? –

+0

是的,但異常不會傳播到調用線程。 – ConditionRacer

+0

通常情況下,在.NET Web應用程序中,您有全局事件。asax - > void Application_Error(object sender,EventArgs e) - 您可以在其中捕獲應用程序中發生的所有錯誤。你有什麼類型的應用程序? – Coastpear

回答

2

的在所描述的情況下,最讓我擔心的事情是該第三方庫中的異常線程終止。一旦線程拋出,你不能通過正確的方式捕獲異常,因爲你不是該線程調用的所有者(並且它不知道它應該向你傳播異常;不像它發生在TPL中,讓說)。因此,即使通過全局處理程序處理此類異常,這可能是錯誤的方式,因爲在任何此類異常之後,lib可能會顯示爲不一致狀態。

所以安全的方式這裏是隔離某個範圍內的lib並在任何異常後重新啓動範圍。比方說,將lib加載到單獨的域中。

+0

我試圖避免在另一個進程中對沙箱進行沙箱,但它看起來可能是唯一的解決方案。我對這個庫沒有任何控制權,但我不得不使用它,原因是我無法進入,並且無法獲得對此問題的支持。我正在尋找解決方法來解決不好的情況。 – ConditionRacer

+1

@ConditionRacer,小修正:C#域名不是其他進程,它們是嵌入到.NET基礎架構中的隔離級別,因此您不必擔心跨應用程序的事情。所以特定的應用程序可以有多個域,因爲大多數應用程序只是隨意使用默認域。附:作爲一個外包商多年,我感到你的痛苦和理解的情況 –

0

我希望這是有益https://msdn.microsoft.com/en-GB/library/system.windows.forms.application.threadexception.aspx

你可以嘗試這樣的事情(這是從文章)

Application.ThreadException += new ThreadExceptionEventHandler (ErrorHandlerForm.Form1_UIThreadException); 

// Set the unhandled exception mode to force all Windows Forms errors to go through 
// our handler. 
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); 

// Add the event handler for handling non-UI thread exceptions to the event. 
AppDomain.CurrentDomain.UnhandledException += 
    new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); 
+1

您只能在Windows窗體應用程序中工作的前兩個示例......第三個示例讓您查看錯誤,但不會阻止關閉應用程序。 –

+0

不幸的是,我想做的不僅僅是記錄異常。我試圖恢復並繼續。 – ConditionRacer

1

如果你的目標是防止因爲這些未處理的異常不在你的控制之下的您的過程提前終止,則存在legacyUnhandledExceptionPolicy設置,您可以添加到您的app.config,以防止未處理的終止整個線程異常處理。

顯然,解決方案並不完美,因爲未處理的異常可能會破壞線程的狀態。但至少這是您可以考慮的選項。

請查看有關此here的文檔以更好地瞭解打開此設置的含義。

app.config必須是這個樣子:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <runtime> 
    <legacyUnhandledExceptionPolicy enabled="1"/> 
    </runtime> 
</configuration> 

編輯: 只是一個想法,但也許上面的設置,結合添加的事件處理程序AppDomain.UnhandledException可以幫助您與您的需要。

使用AppDomain.UnhandledException,您可以檢測到故障,以便您知道何時需要觸發重試,或者是否需要在這些情況下執行其他任何操作。

legacyUnhandledExceptionPolicy設置仍然有助於防止進程停止運行,從而使您有機會執行重試。