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

标签 c# winforms invoke

下面的 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/

相关文章:

javascript - 无法从 html 按钮调用 js 函数

c# - 如何在 C# 中有效地检查来自 URL 的 401 响应?

c# - 占用高 CPU 的非托管方法调用

C#关闭另一个窗体问题,Close();不起作用

c# - 从多个控件获取值的通用方法

c# - 在 C# 中处理跨线程事件的最佳方法是什么

node.js - 我可以使用 lambda :invoke to call AWS Lambda express app?

c# - 如何消除异步函数中循环报告进度的竞争条件?

c# - 分配免费委托(delegate)或其他方式通过地址调用方法?

C# WinForms 托盘应用程序 - 未捕获 Windows 关闭事件