无法捕获FormClosing中抛出的异常

时间:2013-11-28 09:37:06

标签: 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("lets catch this");
    }
  }

我试着像这样抓住它:

  try
  {
    var f = new Form2();
    f.ShowDialog();
  }
  catch (Exception ex)
  { 
    //this is never hit!
    MessageBox.Show("try/catch: " + ex);
  }

抛出异常,从未在我的try / catch中捕获。

可以,然后使用Application.ThreadException += ..抓住它,但此时很难恢复。

我该怎么办?

另外:
我正在使用Windows8 x64 - 该程序的目标平台为x86
我在here附近发现了一个问题,但我的例外情况并非沉默。

更新1
当我附加到进程时,它会像我刚刚手动启动.exe文件一样失败: enter image description here

1 个答案:

答案 0 :(得分:3)

这是预期的行为。

ShowDialog方法不应抛出事件抛出的异常。你正在做的也是错误的做法。您在OnClosing 上的覆盖应是安全的,不会抛出任何错误。如果不是这种情况,它将作为UnhandledException传递。

可以捕获异常,但您应该在OnClosing处理程序中执行此操作。

protected override void OnClosing(CancelEventArgs e)
{
  base.OnClosing(e);
  try {
    throw new Exception("lets catch this");
  }
  catch (Exception e) {
    // Do something with e
  }
}

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

  try
  {
    FormClosingEventArgs e1 = new FormClosingEventArgs(this.closeReason, false);
    this.OnClosing((CancelEventArgs) e1);
    this.OnFormClosing(e1);
  }
  catch (Exception ex)
  {
    Application.OnThreadException(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

如果这是你计划在很多场景中使用的东西,你可能想要为它创建一个接口,以一种很好的结构化方式包装它。对于一次性情况,我不会打扰。