2017-08-29 8 views
-1

私はMDI親子アプリケーションがあります。
Program.csファイルには、ThreadExceptionとUnhandledExceptionの両方のグローバル例外ハンドラがあります。MDI子フォームの "WinForm"グローバル "キャッチ例外"

これらは正常に動作しています。

グローバルレベルで処理されない例外が発生すると、アプリケーションの現在の状態がわからないため、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はフォームかもしれません)。Parentがnullになるか、親が基底クラスから派生するま​​で、親を再帰的にチェックすることができます。

MdiParentフォームのMdiChildrenをループして、例外の原因となったフォームがあるかどうかを確認することもできます。その後、基本クラスから継承する必要はありません。

あなたはファイア・アンド・フォーゲットタイプのスレッドでいくつかの匿名メソッドを持っている場合にも、ThreadExceptionの場合には、これはおそらく動作しないでしょう...

私は1つのプロジェクトだけでグローバルな例外処理を使用します私は、Visual Studioの例外ヘルパーを代わりに取得するため、デバッグモードでは正常に動作しないことを覚えているようですので、これをテストする簡単な方法はありません。一般的な「擬似コード」推奨とみなしてください。

+0

もちろん、スレッドを起動して再びフォームとやりとりすることを期待していない場合は、理論上は例外を呑み込んでフォームを実行し続けることができます(無効な状態、データ腐敗など、あなたはそれをすることができます)。フォームがスレッドの実行が完了するのを待っている場合は、そのレベルでエラーをキャッチしなければなりません(意味のあるタイムアウトを行い、期待されるアクションが完了しなかったことを認識してください)。 –

+0

Systemを使用してスタックトレースにプログラムでアクセスできます。診断。 'stringFileName = new StackTrace().GetFrame(1).GetFileName();'は、フレーム1のファイル名を与えます。フレームを歩くことができます。メソッド名を取得するためのGetFileName() 、タイプなど –

+0

あなたの助けを借りて私は非常に近くになった。私は "new StackTrace(例外、真).GetFrames()"と "bool cancelExit = stackFrame.GetMethod()を使用してforeachループを使用して終わった。ReflectedType.IsSubclassOf(typeof(Project.BaseForm));"しかし、私は壊れたフォームのインスタンスを取得できない/取得できないので、その壊れたフォームを閉じたり破棄したりすることができないことを知りました。ハンドルIDを取得する方法がわかっていればフォームを閉じるには、Windowsメッセージを送信することができます。まだ掘っている。 – goroth

0

私がすでにコメントで述べたように、私はあなたのアプローチが本当に好きではありません。特に、最も一般的な例外をキャッチしているケースが特にあります。

このメッセージは、問題の解決に部分的に役立ちます。クラッシュは、コールスタック、ヒープ上のオブジェクト、CPUレジスタなど、問題を完全に解決するのに役立ちます。How to take a crash dumpを学んでそれを分析してください。 MDIフォームを閉じると、アプリケーションのデータが無効な状態にある可能性があるという事実は無視されます。

しかし、これはコーディングスタイルであり、ここでは説明してはいけません。

あなたができることはAspect Oriented Programming (APO) [Wikipedia]と呼ばれます。アスペクトは、コードのいくつかの部分に適用されるもので、どこにでも明示的に実装する必要はありません。

アスペクトをコードとして実装し、設定ファイルにそのコードを適用する場所を定義します(例:命名規則によって。

魔法はコンパイル時に発生します。通常のコードをコンパイルした後、中間コードウィーバー(ILウィーバー)がILコードを変更し、そのアスペクトをどこにでも挿入します。

PostSharp(商用)またはAfterThought(無料)のようなライブラリが必要です。 PostSharpにはexamples for exception handlingもあり、メッセージボックスを表示するのに簡単に採用できます。

最初に試してみるときには心地よい曲が必要です。そのコードをそのコードに適用する前に、いくつかのチュートリアルに従ってください。

+0

私はMDI子を閉じて、未処理の例外が発生したときにアプリケーションを実行したままにしておくことは悪い習慣ですが、このアプリケーションではすべてのMDIフォームが互いに独立しており、グローバル/静的メソッド/プロパティ/アプリケーション。したがって、このアプリケーションでは、アプリケーション全体を強制終了することなくフォームを削除することは安全です。しかし、私はあなたが送ったリンク/情報が好きで、将来の使用のためにそれらのそれぞれを読むでしょう。 – goroth

関連する問題