当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文件一样失败:
答案 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
如果这是你计划在很多场景中使用的东西,你可能想要为它创建一个接口,以一种很好的结构化方式包装它。对于一次性情况,我不会打扰。