gpt4 book ai didi

c# - 多种形式的异常处理

转载 作者:可可西里 更新时间:2023-11-01 09:03:40 26 4
gpt4 key购买 nike

我在调试时和在运行已编译的 .exe 时看到异常被捕获或未被捕获的不同行为。我有两种形式(Form1 和 Form2)。 Form1 上有一个按钮,它在 Form2 上实例化并调用 ShowDialog。 Form2 上有一个按钮,它有意产生被零除的错误。当我调试时,命中了 Form1 中的 catch block 。当我运行已编译的 .exe 时,它​​没有命中,而是出现一个消息框,指出“您的应用程序中发生了未处理的异常。如果您单击继续,应用程序将忽略此错误并尝试继续。如果您单击退出,应用程序将立即关闭...试图除以零”。我的问题是为什么在调试时和运行 .exe 时会出现不同的行为?如果这是预期的行为,那么是否认为有必要在每个事件处理程序中放置 try/catch block ?这似乎有点疯狂,不是吗?

这是 Form1 的代码。

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

}

private void button1_Click(object sender, EventArgs e)
{
try
{
Form2 f2 = new Form2();
f2.ShowDialog();
}
catch(Exception eX)
{
MessageBox.Show( eX.ToString()); //This line hit when debugging only
}
}
}

这是 Form2 的代码:

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

private void button1_Click(object sender, EventArgs e)
{
int x = 0;
int y = 7 / x;

}
}

最佳答案

是的,这是设计使然,并且与 Windows 窗体的工作方式密切相关。在 Winforms 应用程序中,代码运行以响应 Windows 发布到事件窗口的消息。每个 native Windows 应用程序都包含一个消息循环来检测这些消息。 Winforms 管道确保您的事件处理程序之一运行响应; button1_Click 在您的示例代码中。

大多数 Winforms 控件都实现了自己的事件处理程序。例如,PictureBox 有一个 Paint 事件处理程序,可确保将其图像绘制到屏幕上。这一切都是自动完成的,您无需自己编写任何代码来完成这项工作。

但是当这段代码抛出异常时会出现问题,您无法捕获此类异常,因为没有涉及您自己的代码。换句话说,您没有地方可以注入(inject)自己的 try block 。您自己的程序代码的最后一部分是启动消息循环的代码。 Application.Run() 方法调用,通常在 Program.cs 中。或者,如果显示对话框,则调用 Form.ShowDialog()。这些方法中的任何一个都会启动消息循环。在 Application.Run() 调用周围放置一个 try block 没有用,应用程序将在捕获异常后终止。

为了解决这个问题,Winforms 消息循环代码在调度事件的代码周围包含一个 try block 。它的catch子句显示你提到的对话框,它是由ThreadExceptionDialog类实现的。

进入您的问题的要点:这个 catch 子句确实妨碍了您在调试时对代码问题进行故障排除。只有在没有处理异常的 catch block 时,调试器才会在出现异常时停止。但是当您的代码抛出异常时,您会想在调试时了解它。前面提到的消息循环中的代码知道是否附加了调试器。如果是,它会在没有 try/catch block 的情况下分派(dispatch)事件。现在,当您的代码抛出异常时,没有 catch 子句来处理它,调试器将停止程序,让您有机会找出问题所在。

也许您现在明白了为什么您的程序会这样运行。调试时,消息循环中的 catch 子句被禁用,从而使 Form1 代码中的 catch 子句有机会捕获异常。如果您不这样做,消息循环 catch 子句会处理异常(通过显示对话框)并防止异常展开到 Form1 代码。

您可以通过调用 Application.SetUnhandledExceptionMode() 方法并传递 UnhandledExceptionMode.ThrowException 来阻止使用消息循环 catch 子句。在 Main() 方法中执行此操作,在 Application.Run() 调用之前。现在您的程序在任何一种方式下的行为都相同。

这通常不是一个坏主意,让用户在异常对话框中选择“继续”是一个值得怀疑的功能。在这种情况下,请务必为 AppDomain.UnhandledException 事件实现事件处理程序,以便至少为用户提供一些诊断信息。

关于c# - 多种形式的异常处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1775887/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com