9

我遇到过这样的情况。WinForms 应用程序有两种形式。主窗体有一个按钮,当用户单击它时,会显示模态对话框。对话框表单也有一个按钮,当用户单击它时,会引发异常。

当应用程序在调试器下运行并自行运行时,异常处理会有所不同。这是重现此行为的最少代码:

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 窗体程序集在 Visual Studio 托管进程之外运行的方式有关。看到这个:

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 回答