2017-08-29 75 views
-1

我有一個MDI父/子應用程序。
在Program.cs文件中,我針對ThreadException和UnhandledException都有一個全局異常處理程序。WinForm「全局」MDI子窗體「唯一」捕獲異常

那些工作正常。

當我在全局級別得到未處理的異常時,在UnhandledException處理程序內部調用Environment.Exit(1)來關閉應用程序,因爲我不知道應用程序的當前狀態。

在子窗體中,我「通常」將以下內容添加到事件處理程序中。

try 
{ 
    // Some Code 
} 
catch (Exception ex) 
{ 
    HandleException(ex); 
    MessageBox.Show("Some message"); 
    this.Close(); 
} 

我想知道是否有將我所有的孩子形成了全球性的異常處理程序(我有他們繼承鹼基形式),可以捕獲異常,並關閉子窗體不關閉的方式整個應用程序。
這樣,如果開發人員「忘記」在事件上添加try catch塊,它不會轟炸整個應用程序。

+0

我同意崩潰轉儲會很方便。我有一個全局的異常記錄器,可以保存堆棧跟蹤,一些性能設置等等,它們保存在一個sql數據庫中供審閱,但我不想因爲有人忘記添加try catch而終止應用程序像在數字文本框中輸入字符串一樣簡單。 – goroth

回答

0

我同意這通常是一個糟糕的主意,但是如果您的全局異常處理程序具有「發件人」對象,則可以嘗試使用sender.GetType()來獲取該對象的類型。您可以通過說if (sender.GetType().IsSubclassOf(typeof (BaseClass))) { // then do something }來查看它是否繼承了您的基本形式。

如果發件人是子窗體的子控件(而不是窗體本身),那麼您可能需要使用輔助方法遍歷幾個級別的祖先來查找父窗體(例如:發件人可能是一個文本框,sender.Parent可能是一個面板,sender.Parent.Parent可能是表單)。您可以遞歸檢查父項,直到父項爲空,或者父項來自基類。

您也可以循環遍歷MdiParent窗體的MdiChildren,以查看它們中是否有任何窗體導致異常。那麼你不需要從基類繼承。

此外,在ThreadException的情況下,如果你有在一些匿名方法發射後不管型線,這將有可能無法正常工作......

我只在一個項目中使用全局異常處理,並且我似乎記得它在調試模式下無法正常工作,因爲您獲得了Visual Studio異常幫助程序,所以我沒有快速測試此方法 - 只是將其視爲一般「」僞代碼「建議。

+0

當然,如果你啓動一個線程並且你不希望它再次與你的表單交互,那麼理論上你可以吞下異常,表單將繼續運行(再次 - 爲無效狀態,數據創建巨大潛力腐敗等,但你可以做到)。如果您的表單正在等待線程完成執行,那麼您必須捕獲該級別的錯誤(通過有意義的超時並意識到預期的操作從未完成)。 –

+0

您可以使用System以編程方式訪問堆棧跟蹤。診斷。 'string fileName = new StackTrace()。GetFrame(1).GetFileName();'會爲您提供第1幀的文件名 - 您可以遍歷幀,還有其他方法,如GetFileName()獲取方法名,類型等。 –

+0

在你的幫助下,我非常接近。我結束了對「新的StackTrace(exception,true).GetFrames()」,然後使用「bool cancelExit = stackFrame.GetMethod()。reflectedType.IsSubclassOf(typeof(Project.BaseForm));」;但後來我發現,因爲我沒有/無法得到崩潰的窗體的實例,所以我無法關閉/處理那個破損的窗體......如果我只能弄清楚如何獲取窗體的窗體ID窗體,我可以發送一個Windows消息來關閉該窗體。仍在挖掘。 – goroth

0

正如我在評論中已經說過的,我不太喜歡你的方法,特別是你正在捕捉最一般的異常的情況。

該消息只能部分幫助您解決問題。崩潰可以幫助你完全解決問題,包括調用堆棧,堆上的對象,CPU寄存器等。只要學習How to take a crash dump並分析它。通過關閉MDI窗體,您忽視的事實是你的應用程序的數據可能會處於無效狀態

而行,這就是編碼風格,也許不應該在這裏討論。

你可以做什麼叫做Aspect Oriented Programming (APO) [Wikipedia]。方面是適用於你的代碼的幾個部分,你不想明確地在任何地方實現它。

您將一個方面實現爲代碼,然後在配置文件中定義要應用該代碼的位置,例如,通過命名約定。

魔法發生在編譯時。編譯普通代碼後,中間代碼編織器(IL-weaver)修改IL代碼並在任何地方插入方面。

您需要一個庫,如PostSharp(商業)或AfterThought(免費)。 PostSharp甚至有examples for exception handling,可以很容易地用於顯示消息框。

當你第一次嘗試它的時候,它需要一些思維彎曲,所以一定要遵循一些教程,然後再將這個conceopt應用到你的代碼中。

+0

我同意你關閉MDI子代並在發生未處理的異常時運行應用程序是不好的做法,但在此應用程序中,所有MDI表單都是相互獨立的,並且內部沒有全局/靜態方法/屬性/變量應用程序。所以在這個應用程序中,殺死一個表單而不殺死整個應用程序是安全的。但我確實喜歡你發送的鏈接/信息,並且會閱讀它們中的每一個以供將來使用。 – goroth