WinForms应用程序中的异常处理行为,它使用模式对话框

Den*_*nis 9 c# exception-handling winforms

我遇到过这样的情况.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();
    }
}
Run Code Online (Sandbox Code Playgroud)

调试时,引发异常会关闭对话框,Form1.button1_Click中的异常处理程序会处理异常.

在运行应用程序本身时,引发异常不会关闭对话框.而不是这样,默认调用Application.ThreadException处理程序.

为什么(以及为什么)行为有所不同?如何使它相互一致?

Mel*_*den 8

在Program.Main()中尝试这个:

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

原因是Windows Forms程序集在Visual Studio Hosting进程之外运行的方式.看到这个:

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

如果将上面的代码行设置为:

Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
Run Code Online (Sandbox Code Playgroud)

并在VS中运行它,您将看到默认行为是什么 - 一旦您跨过代码中的初始异常,将显示您引用的对话框.根据您是以托管模式还是独立模式运行,默认值会有所不同.

好吧,"为什么"在MS链接中有所涉及 - 错误发生在事件处理程序中,该处理程序位于不同的线程上.默认行为是仅在WinForms下对待它.如果在调用对话框后放置此行:

throw new Exception("Bah!");
Run Code Online (Sandbox Code Playgroud)

并保持CatchException上的行为,您将看到它如您所期望的那样转到您的异常处理程序.它只是事件处理程序中的异常,它以不同的方式处理.希望有所帮助.

  • 了解; 为什么/为什么我会说这只是.NET框架的一个怪癖.我可能会更正,我有兴趣知道是否有人知道这种行为因运行应用程序的上下文而异的原因.我同意这有点儿了. (2认同)