1


0

treeview.Nodes.Add / treeview_AfterSelectイベント境界を越えて例外をキャッチする

WinFormsプログラムにMyOwnExceptionをスローする場所があります。

void CodeThatThrowsMyOwnException()
{
    ...
    throw new MyOwnException("Deep Inside");
    ...
}

スタックのさらに上には、単純なtry / catchブロックがあります

try
{
    CodeThatThrowsMyOwnException();
}
catch (MyOwnException moe)
{
    MessageBox.Show("Hit this point in the code! Hurray!");
}
MessageBox.Show("Later, alligator.");

同僚のコンピューター(VS 2008 SP1を私のように実行している)に、ダイアログボックスが表示されます。 私のコンピューターでは、例外をキャッチしたり、ダイアログボックスを表示したりすることはありません。 例外をスローする行のコード(CodeThatThrowsMyOwnException)の奥深くにブレークポイントを配置すると、その行のブレークポイントにヒットします。 F5([デバッグ]> [実行])を押すと、渡されたcatchブロックがスキップされ、「Later、alligator」メッセージが表示されます。

実際に「void CodeThatThrowsMyOwnException()\ {throw new MyOwnException( "Shallow");}」コードをコードに貼り付け(実際のコードを呼び出す代わりに)、文字通り「CodeThatThrowsMyOwnException();」を呼び出しますただし、tryブロックではcatchブロックにメッセージが表示されます。

私が知る限り、私はスレッドを作成しておらず、すべての例外をキャッチするが、関連するプロジェクトで何も見つからないtry \ {} catch \ {}ブロックを探しました(そして、それらがそこにあった場合、なぜcatchブロックは同僚のマシンでまだ動作しますか?)

奇妙なことに、実行可能ファイルをダブルクリックしてコードを実行すると、マシン上で未処理の例外が発生し、同僚のマシンでも同じ例外が発生します。 これは、私が次のことを試すように導いた手がかりです。

コード内のthrow MyOwnException( "Deep Inside")行にブレークポイントを配置すると、コールスタックには、例外ハンドラーと「throw MyOwnException( "Deep Inside"」を呼び出す場所の間に「[External Code]」という行が含まれます。 「)」。 try / catch MyOwnExceptionブロックをスローからさらに遠ざけた場合(ただし、[外部コード]のこちら側では、try catchブロックを配置した場所(関数チェーンの関連部分の周り)で例外をキャッチできます):

try
{
    CodeChain(...);
}
catch (DrawException de)
{
    MessageBox.Show("Hurray!"); // being executed, but only on the 'throw' side of the [External Code] part of the call stack
}

しかし、[外部コード]の外側(スタックの下)に足を踏み入れると、例外は発生しません。 これは予想外です:

try
{
    treeview.Nodes.Add(treeNode); // triggers the aforementioned chain of code with MyOwnException thrown
}
catch (DrawException de) // no matter what I do, this will not handle my cursed MyOwnException
{
    MessageBox.Show("Hurray!"); // not being executed
}

これが私の問題の中心です。多くのテストを実行する必要があるため、コールスタックを追い上げることはできません(以下を参照)。

私はある種の仮説を持っています。それは、彼のデバッガーがスレッドの境界を越えて(または外部コードを越えて、つまり、 デバッガーでのWindows GUIイベント)、他の3つの状況(私のデバッガー(64ビット拡張なし)およびいずれかのマシンがWindowsエクスプローラーからEXEを実行する場合)では、例外はそのスレッドで本当に処理されません。

それでは、この例外をどのようにキャッチしますか? treeview.AfterSelectを使用しないようにシステム全体を再設計しますか? 明らかに、例外の制限を理解していません。

潜在的な問題?

  • システムをモジュール化して再利用可能な状態に保つために、代理人がいます。 Can モジュールの境界を越えて、デリゲートを介して例外がスローされますか?

私が達成しようとしていること(ハーネスのテスト)と例外が必要な理由

自動テストハーネスでこれを使用しています。 これらの例外的な状況を見つけて問題を絞り込むアクションスクリプト(テキストファイル)を再生することにより、複雑なGUIシステムの非常に難しい論理的/アルゴリズム的なバグを修正する必要があります。 (おそらく、私のプログラムでは、デザインの書き直しまたはリファクタリングに関してこれに対する良い回避策はありません:このQAフェーズでこれらの例外をキャッチし、出荷する前にバグを修正する必要があります(アルゴリズムの特別な場合)ユーザーにそのようなバグのあるソフトウェアを使用させます。 楽しみのためにエキゾチックな制御フローの例外を使用しているわけではありません(cf. Int32.Parse)。)

1 Answer


1


treeview_AfterSelectは、あなたが[外部コード]と呼んでいるものによって、_ほとんど_の時間と呼ばれます。 これらは、ユーザーがノードを選択した結果、またはフォームがロードされていてノードを追加している場合でも発生します(未処理の例外で発生する可能性があります)。

何らかの理由でAfterSelectハンドラーが例外をスローする場合、呼び出しコードに依存してそれらの例外を処理することはできません。 そうしないと、AfterSelectが呼び出される他の方法により、未処理の例外が発生する可能性があります。