9

私はそのような状況に遭遇しました。WinFormsアプリケーションには2つの形式があります。メインフォームにはボタンがあり、ユーザーがそれをクリックすると、モーダルダイアログが表示されます。ダイアログフォームにもボタンがあり、ユーザーがそれをクリックすると、例外がスローされます。

アプリケーションがデバッガーで実行されている場合とそれ自体を実行している場合では、例外処理が異なります。この動作を再現する最小限のコードを次に示します。

public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        try
        {
            using (var dialog = new Form2())
            {
                dialog.ShowDialog();
            }
        }
        catch (Exception ex)
        {
            MessageBox.Show("Oops! " + ex.Message);
        }
    }
}

public partial class Form2 : Form
{
    public Form2()
    {
        InitializeComponent();
    }

    private void button1_Click(object sender, EventArgs e)
    {
        throw new NotImplementedException();
    }
}

デバッグ時に例外を発生させるとダイアログが閉じ、Form1.button1_Clickの例外ハンドラーが例外を処理します。

アプリケーション自体を実行しているときに例外を発生させても、ダイアログは閉じません。これの代わりに、デフォルトのApplication.ThreadExceptionハンドラーが呼び出されます。

なぜ(そして何のために)動作が異なるのですか?それを互いに一致させる方法は?

4

1 に答える 1

8

Program.Main()でこれを試してください:

[STAThread]
static void Main()
{
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException);
    Application.Run(new Form1());
}

その理由は、WindowsフォームアセンブリがVisualStudioHostingプロセスの外部で実行される方法に関係しています。これを参照してください:

http://msdn.microsoft.com/en-us/library/system.windows.forms.application.threadexception.aspx

上記のコード行を次のように設定した場合:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);

VSで実行すると、デフォルトの動作がわかります。コードの最初の例外をステップオーバーすると、参照するダイアログボックスが表示されます。デフォルトは、ホストモードとスタンドアロンモードのどちらで実行するかによって異なります。

「なぜ」はMSリンクでカバーされています。エラーは、別のスレッドにあるイベントハンドラーで発生します。デフォルトの動作では、WinFormsでのみ、これを別の方法で処理します。ダイアログの呼び出しの後にこの行を配置すると、次のようになります。

throw new Exception("Bah!");

そして、CatchExceptionの動作を維持すると、期待どおりに例外ハンドラーに送られることがわかります。異なる方法で処理されるのは、イベントハンドラーの例外のみです。お役に立てば幸いです。

于 2012-04-17T08:32:06.803 に答える