2013-09-27 49 views
2

我有一個爲.NET 4 Full Framework編寫的WPF應用程序。該應用程序使用SQL Anywhere作爲其數據庫。我的應用程序有一個未處理的異常處理程序,它總是將錯誤記錄到程序的自定義事件日誌中。然後它將錯誤消息顯示給用戶。該程序還會在事件日誌中發送消息,以便隨時進行調試。.NET程序在什麼情況下會終止?

該應用程序安裝在運行Windows 7並具有8 GB RAM的用戶筆記本電腦上。在本機上啓動時,將顯示啓動畫面,然後顯示程序的主窗口。在繪製完成後不到一秒鐘,程序就會消失。沒有顯示錯誤消息。

檢查事件日誌顯示程序寫的最後一條消息是它正在檢查數據庫中是否存在用戶。沒有錯誤消息。

下面顯示的最後一條消息的代碼是,做一些參數檢查方法的調用,然後執行以下EF查詢:

LPRCore.CarSystem.User user = null; 

IQueryable<User> query = from u in context.Users 
         from m in context.Members.Where(m => m.UserId == u.UserId) 
                .DefaultIfEmpty() 
         where u.LoweredUserName == userName.ToLower() && m == null 
         select u; 
try { 
    user = query.SingleOrDefault(); 

} catch (Exception ex) { 
    .... 
} 

我不能告訴,如果在代碼catch塊被稱爲。我的懷疑是它被召喚了,並且在那裏發生了異常。

我的問題是,如果在catch塊中發生異常,那麼如果沒有其他異常處理程序來捕獲錯誤,上層的未處理異常處理程序是否會捕獲該異常?或者它會導致程序死亡而不報告任何內容?

+0

運行連接(遠程)調試器時會發生什麼? – 2013-09-27 21:04:00

+1

我們還通過添加Application.ThreadException + = OnApplicationThreadException和未處理的處理程序來捕獲更多。 –

+0

即時通訊假設你也想深究這個問題的底部。首先您可以檢查客戶端PC上的事件查看器。如果沒有「好的」異常或消息,那麼當應用程序退出時,您將不得不拔出Windbg並獲取轉儲。 – wal

回答

7

我的問題是,如果在catch塊中發生異常,那麼如果沒有其他異常處理程序來捕獲錯誤,上層的未處理異常處理程序是否會捕獲該異常?或者它會導致程序死亡而不報告任何內容?

異常會向上蔓延,應該被未處理的異常處理程序捕獲。

這就是說,一些例外將不會被捕獲,如StackOverflowException。異常塊(或DB提供者...?)中的代碼也可能終止該過程(即:調用Environment.Exit或其他類似的東西),但這種方式不允許異常處理工作。

+2

對我來說,最常見的是堆棧溢出,對於我來說,幾乎每次我通過錯誤地實現一個基於字段的屬性來完成它,比如'public object Thing {get {return Thing; }}'而不是'return thing;'...我認爲代碼分析能夠爲我抓到一些這樣的東西:)。如果我是你,我的第一個檢查就是執行'LoweredUserName'' –

+0

@JohnGardner當你用Release模式(優化)編譯這個('get'訪問器或自己調用它)時,它可能不會填充堆棧,因爲調用可能是內聯或其他內容,而程序只是永遠遞歸。 –

+0

@JohnGardner:'LoweredUserName'是由Entity Framework生成的屬性。它在其他地方沒有造成任何問題該軟件已經過測試併發布。這個問題發生在一臺特定的客戶端計算機上。我從來沒有見過它發生在任何其他系統之前。我是積極的,問題不在那裏,或者每個EF模型都會有問題,我永遠也不會得到這個程序來發布。 –

3

總之未處理的異常

記住,至少有2個地方,你應該記錄未處理的異常。 應用程序的AppDomain UnhandledException處理器的Application.DispatcherUnhandledExceptionEACH

如果你不抓住這些,應用程序將終止。

另外請注意,由於.NET 2.0中線程中的未處理異常傳播到應用程序,導致它終止(不是線程的應用程序)。在.NET 1.1中,線程悄然死亡。

從.NET Framework 2.0版開始,公共語言運行庫允許線程中大多數未處理的異常自然進行。在大多數情況下,這意味着未處理的異常會導致應用程序終止。

Exceptions in Managed Threads

Application對象的ThreadException處理器似乎只趕上從應用程序主線程(或可能更正確的應用調度線程引發的異常)傳播了異常。其他的一切似乎都出現在應用程序域的UnhandledException處理程序中。

所以除了一個Application.UnhandledException處理程序添加domain.UnhandledException這樣的:

static void Main(string[] args) 
{ 
    Application.ThreadException += ApplicationThreadException; 


    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; 
} 

static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) 
{ 
    // Log exception here and exit application, you can't recover now. 
} 

這樣一點要注意,如果你最終在這些「全局」異常左撇子,你的應用程序處於未知狀態,但是唯一有效的做法是記錄問題並退出/重新啓動應用程序;即使您仍然可以讓應用程序運行,您現在也無法恢復。

+0

我不知道AppDomain.UnhandledException處理程序。我將不得不爲下一個版本添加一個。這並沒有幫助我找到現在正在殺死我的程序的問題。 –

+0

@ Pete-stensones如何將AppDomain UnhandledException處理程序添加到庫類(即沒有單個入口點的程序)?或者是不需要的? – Rikalous

+0

您通常會在您的主機程序的program.cs中添加應用程序域未處理的異常處理程序;因爲通常您記錄錯誤並讓應用程序終止。 –

相關問題