Control.Invoke展开外部异常并传播内部异常

Jua*_*uan 6 c# invoke winforms

以下MessageBox.Show调用显示"内部".这是一个错误吗?

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"
    }
}
Run Code Online (Sandbox Code Playgroud)

Chr*_*ris 6

我查看了参考源System.Windows.Forms.Control代码,处理的代码Invoke如下所示:

try {
    InvokeMarshaledCallback(current);
}
catch (Exception t) {
    current.exception = t.GetBaseException();
}
Run Code Online (Sandbox Code Playgroud)

GetBaseException:

public virtual Exception GetBaseException() 
{
    Exception inner = InnerException;
    Exception back = this;

    while (inner != null) {
        back = inner;
        inner = inner.InnerException;
    }

    return back;
}
Run Code Online (Sandbox Code Playgroud)

显然它就像设计一样.来源中的评论没有解释为什么他们这样做.

编辑:一些现在已经消失的网站声称这条评论来自微软的一个人:

根据记录中的winform确认,我们的分析是正确的根本原因,这种行为是有意的.原因是为了防止用户看到太多的Windows.Forms内部机制.这是因为winform的默认错误对话框还利用Application.ThreadException来显示异常详细信息..Net Winform团队修剪其他异常信息,以便默认错误对话框不会向最终用户显示所有详细信息.

此外,一些MSFT已经建议改变这种行为.但是,.Net Winform团队认为将异常更改为throw是一个重大变化,因此WinForms将继续向Application.ThreadException处理程序发送最内层异常.

  • @Juan在`System.Windows.Forms.Control`下查看`InvokeMarshaledCallbacks()`。 (2认同)