下面的 MessageBox.Show
调用显示“Inner”。这是错误吗?
private void Throw()
{
Invoke(new Action(() =>
{
throw new Exception("Outer", new Exception("Inner"));
}));
}
private void button1_Click(object sender, EventArgs e)
{
try
{
Throw();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message); // Shows "Inner"
}
}
最佳答案
我查看了 System.Windows.Forms.Control
的引用源,处理 Invoke
的代码如下所示:
try {
InvokeMarshaledCallback(current);
}
catch (Exception t) {
current.exception = t.GetBaseException();
}
GetBaseException
:
public virtual Exception GetBaseException()
{
Exception inner = InnerException;
Exception back = this;
while (inner != null) {
back = inner;
inner = inner.InnerException;
}
return back;
}
很明显这是设计使然。源代码中的评论没有解释他们为什么这样做。
编辑:一些现在已经消失的网站声称这条评论来自微软的一个人:
Based on the winform comfirmation in the record, our analysis is correct of the root cause and this behavior is intended. The reason was to prevent the user from seeing too much of the Windows.Forms internal mechanisms. This is because the winform's default error dialog also leverages Application.ThreadException to show the exception details. .Net Winform team trims the other exceptions information so that the default error dialog will not display all the details to the end user.
Also, some MSFTs have sugguested to change this behavior. However, .Net Winform team thinks that changing the exception to throw is a breaking change and for this reason WinForms will keep sending the innermost exception to the Application.ThreadException handler.
关于c# - Control.Invoke 展开外部异常并传播内部异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28054525/