Winforms Can';在FormClosing中引发了t捕获异常

Winforms Can';在FormClosing中引发了t捕获异常,winforms,visual-studio-2010,c#-4.0,exception-handling,Winforms,Visual Studio 2010,C# 4.0,Exception Handling,当FormClosing中抛出异常时,我无法通过正常的try/catch捕获它-为什么不呢 例如: public partial class Form2 : Form { public Form2() { InitializeComponent(); } protected override void OnClosing(CancelEventArgs e) { base.OnClosing(e); throw new Exception

当FormClosing中抛出异常时,我无法通过正常的try/catch捕获它-为什么不呢

例如:

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

    protected override void OnClosing(CancelEventArgs e)
    {
      base.OnClosing(e);
      throw new Exception("lets catch this");
    }
  }
我试着像这样抓住它:

  try
  {
    var f = new Form2();
    f.ShowDialog();
  }
  catch (Exception ex)
  { 
    //this is never hit!
    MessageBox.Show("try/catch: " + ex);
  }
public partial class Form2 : Form
{
    // I'm using the event here, but if this class in turn is a base for another class, you might as well override the method. (Event will still work, since events allow multiple handlers when using the default event handlers.)
    private void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        try
        {
            // Action that might throw an exception
            throw new Exception("Some exception");
        }
        catch (Exception ex)
        {
            OnClosingException = ex;
        }
    }

    public Exception OnClosingException { get; protected set; }
}

// When calling
var f = new Form2();
f.ShowDialog();
if (f.OnClosingException != null) // Re-throw the exception wrapped in another exception that describes the problem best
    throw new InvalidOperationException("Some message", f.OnClosingException); // Might not always be InvalidOperationException
// Instead of re-throwing you can also just handle the exception
异常被抛出,只是在我的try/catch中从未捕获。

但是,我可以使用
Application.ThreadException+=..
捕获它,但在这一点上很难恢复

我能做什么?

此外:
我使用的是Windows8 x64,该程序具有targetplatform x86
我发现了一个与我的问题相近的问题,但我的例外并不是沉默的

更新1
当我连接到进程时,它会像我刚刚手动启动.exe文件一样失败:
这是预期的行为

该方法不应该抛出它的事件抛出的异常。你所做的也是错误的方法。您的覆盖应该是安全的,不会引发任何错误。如果不是这种情况,则将其作为未处理的异常进行传递

您可以捕获异常,但应该在处理程序中捕获

负责此行为的代码如下所示:

  try
  {
    FormClosingEventArgs e1 = new FormClosingEventArgs(this.closeReason, false);
    this.OnClosing((CancelEventArgs) e1);
    this.OnFormClosing(e1);
  }
  catch (Exception ex)
  {
    Application.OnThreadException(ex);
  }
您的问题的解决方案可以是这样的:

  try
  {
    var f = new Form2();
    f.ShowDialog();
  }
  catch (Exception ex)
  { 
    //this is never hit!
    MessageBox.Show("try/catch: " + ex);
  }
public partial class Form2 : Form
{
    // I'm using the event here, but if this class in turn is a base for another class, you might as well override the method. (Event will still work, since events allow multiple handlers when using the default event handlers.)
    private void Form2_FormClosing(object sender, FormClosingEventArgs e)
    {
        try
        {
            // Action that might throw an exception
            throw new Exception("Some exception");
        }
        catch (Exception ex)
        {
            OnClosingException = ex;
        }
    }

    public Exception OnClosingException { get; protected set; }
}

// When calling
var f = new Form2();
f.ShowDialog();
if (f.OnClosingException != null) // Re-throw the exception wrapped in another exception that describes the problem best
    throw new InvalidOperationException("Some message", f.OnClosingException); // Might not always be InvalidOperationException
// Instead of re-throwing you can also just handle the exception

如果这是您计划在很多场景中使用的东西,那么您可能希望为此制作一个接口,以一种良好的结构化方式将其打包。对于一次性场景,我不想麻烦。

如果程序是为调试而启动的(F5),或者是在正常启动后由调试器连接的(Ctrl+F5),则程序的行为有时会有所不同。如果附加到进程,会发生什么?它是模式对话框吗?@helb yes-
ShowDialog
是modal@Dialecticus它显然抛出了一个未经处理的例外。。更新我的问题你能在一些32位的窗口上测试这个程序吗?还有,在一些旧窗口上?如果更改目标平台会发生什么?为什么要用try-catch包装所有事件处理程序?为什么不将异常保存在
OnThreadException
事件处理程序中?@dialogicus,因为原始海报想要捕捉它?另一个原因是良好的设计。未处理的事件表明代码有问题,因为这是您不期望的。如果您希望一个方法抛出异常,那么您可以捕获它,并从中优雅地恢复。未处理的异常通常意味着您无法安全恢复,并且仍然处于可靠状态。您不应该用try-catch来包装每个事件处理程序,只有在您期望可以处理异常时。然而,当触发事件时,通常最好总是将其包装在一个try-catch中。我不知道其他程序员对此有何感受,但我真的希望有一个catch来捕获所有意外的异常,在这个catch-all中,我很可能只会通知用户和/或将异常写入日志文件。应用程序处于故障状态的可能性很低,但即使如此,用户还是会收到警告。我真的不想用try-catch来包装所有的事件处理程序来覆盖那些意外的异常。我感觉很像@dialogicus——因为我不想用“genrel”try/catch来包装每个事件处理程序。话虽如此-@Aidiakapi回答了我的问题,并解释了为什么我不能像我想的那样捕捉异常。但是为什么使用
Application.OnThreadException(ex)
而不是直接抛出异常更好呢?我说过,代码就是负责该行为的代码。它由System.Windows.Forms.Form类定义。如果您不想要常规的try-catch语句,为什么该语句会出现在示例代码中。很好地解释了异常的类型,以及应该如何处理它们。我不知道你从哪里读到我的建议,在每个事件处理程序周围放置一个通用的try-catch。我的答案中没有这一点,我的“解决方案”是您在问题中提供的代码的镜像。