This is the expected behavior.
The ShowDialog
method isn't supposed to throw the exceptions that it's events throw. What you're doing is also the wrong approach. Your override on OnClosing
should be safe and not throw any errors. When this isn't the case it's passed off as an UnhandledException.
You can catch the exception, but you should do it in your OnClosing
handler.
protected override void OnClosing(CancelEventArgs e)
{
base.OnClosing(e);
try {
throw new Exception("lets catch this");
}
catch (Exception e) {
// Do something with e
}
}
The code responsible for this behavior stripped down looks like:
try
{
FormClosingEventArgs e1 = new FormClosingEventArgs(this.closeReason, false);
this.OnClosing((CancelEventArgs) e1);
this.OnFormClosing(e1);
}
catch (Exception ex)
{
Application.OnThreadException(ex);
}
A solution to your problem could be something like this:
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
If this is something you're planning on using in a lot of scenario's you might want to make an interface for this to wrap it all up in a nice structured way. For a one time scenario I wouldn't bother.