我在活动中遇到问题" textbox验证"。 触发时,如果我抛出异常,则不会返回try catch块。
try
{
new form().showdialog();
}
catch(exception e)
{
console.writeline("ok");
}
然后这就留在这里,不要进入捕获:
private void TB_Validating(object sender, CancelEventArgs e)
{
throw new Exception("aaa");
}
而是在catch代码上打印错误
private void TB_Click(object sender, CancelEventArgs e)
{
throw new Exception("aaa");
}
有人能告诉我原因及其解决方案吗?
答案 0 :(得分:4)
"为什么"是一个很长的painful story,在SO答案中并不适合。黄金法则是异常必须永远不会导致调度程序循环终止。通过调用Application.Run()来获取调度程序循环,就像在Main()入口点或Form.ShowDialog()中一样,在此片段中完成。正是该循环确保ShowDialog()在关闭对话框之前不会返回。
Winforms通过在调度程序循环中使用try / catch-em-all语句来观察该规则。如果事件处理程序抛出异常,它会引发Application.ThreadException事件。如果您没有替换或禁用事件处理程序(您应该),那么您将看到ThreadExceptionDialog,它允许用户赌博"继续"或明智地点击"退出"。
但是,调试时,catch-em-all处理程序非常不方便。它妨碍了诊断未处理的异常。因此,Winforms会检查您是否进行调试,如果您这样做,不将使用try / catch-em-all而不会引发ThreadException事件。这对你的代码片段中的代码有很大的副作用,现在catch语句 似乎工作得很好。但是一旦你按照用户的方式运行你的程序,没有调试器,它就永远不会捕获任何东西。
所以冷酷的事实是在事件处理程序中抛出异常是错误的。除了不可思议的ThreadExceptionDialog之外,没有任何人可以捕获它。而不是抛出,你必须做异常处理程序会做的事情。对于应该是ErrorProvider的Validating事件,给用户一个温和的提示,即他的数据输入不正确。或者设置e.Cancel = true以强制他输入有效数据。
答案 1 :(得分:0)
事件处理程序TextBoxValidating
未在表单的ShowDialog方法中调用。而是从GUI线程消息泵调用它(您可以在此处找到Windows消息泵的基本描述https://en.wikipedia.org/wiki/Message_loop_in_Microsoft_Windows)。
这就是为什么你不能在你的代码中捕获它(因为你的代码没有调用该方法)。
您可以在此处理异常:
Application.ThreadException += ...
我不知道为什么从ShowDialog消息思想中调用Button Click处理程序。