简体   繁体   中英

c# winform textbox Validating unhandled exception

I have a problem on the event "textbox Validating". when fired, if I throw an exception, this doesn't return to the try catch block.

try
{
   new form().showdialog();
}
catch(exception e)
{
   console.writeline("ok");
}

then this stay here and don't go in catch:

private void TB_Validating(object sender, CancelEventArgs e)
{
   throw new Exception("aaa");
}

instead this prints the error on catch code

private void TB_Click(object sender, CancelEventArgs e)
{
   throw new Exception("aaa");
}

Can anyone suggest me the reason and its solution ?

The "why" is a long and painful story that doesn't fit that well in an SO answer. Golden rule is that an exception must never cause the dispatcher loop to terminate. You get the dispatcher loop to loop by calling Application.Run(), as is done in your Main() entrypoint, or Form.ShowDialog() as is done in this snippet. It is that loop that ensures that ShowDialog() does not return until you close the dialog.

Winforms observes that rule by having a try/catch-em-all statement in the dispatcher loop. It raises the Application.ThreadException event if an event handler throws an exception. If you don't replace or disable the event handler (you should) then you get to see the ThreadExceptionDialog, the one that lets the user gamble at "Continue" or wisely click "Quit".

That catch-em-all handler is however very inconvenient when you debug. It gets in the way of diagnosing unhandled exceptions. So Winforms checks if you debug and if you do will not use the try/catch-em-all and not raise the ThreadException event. That has a big side-effect on the code in your snippet, now that catch statement does seem to work just fine. But as soon as you run your program the way your user will do, without a debugger, then it never catches anything.

So the cold hard fact is that throwing an exception in an event handler is just the wrong thing to do. There isn't anybody around to catch it, other than the wonky ThreadExceptionDialog. Instead of throwing, you must do what an exception handler would do. For a Validating event that ought to be ErrorProvider, giving the user a gentle hint that his data entry is not correct. Or setting e.Cancel = true to force him to enter valid data.

The event handler TextBoxValidating is not called inside the ShowDialog Method of the Form. Instead it is called from the GUI Thread Message Pump (You can find a basic description of the Windows message pump here https://en.wikipedia.org/wiki/Message_loop_in_Microsoft_Windows ). Which is why you can not catch it in your code (because your code does not call the method).

You can handle the exception here:

  Application.ThreadException += ... 

I do not know why the Button Click handler is called from inside the ShowDialog message thought.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM