【问题标题】:Control.Invoke unwraps the outer exception and propagates the inner exception insteadControl.Invoke 解开外部异常并传播内部异常
【发布时间】:2015-01-20 20:26:19
【问题描述】:

下面的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"
    }
}

【问题讨论】:

  • 我注意到await Task.Run() 不相关。你应该从你的问题中省略它,因为它只会分散你所问问题的注意力。
  • 这很有趣。如果我们再添加一个内部异常,它也会给我们。
  • 标记:在将其标记为 this other one 的重复之前,请注意实际阅读问题?

标签: c# winforms invoke


【解决方案1】:

我查看了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;
}

显然它是这样设计的。源代码中的 cmets 没有解释他们为什么这样做。

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

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

此外,一些 MSFT 已建议更改此行为。然而,.Net Winform 团队认为将异常改成 throw 是一种破坏 更改,因此 WinForms 将继续向 Application.ThreadException 处理程序发送最里面的异常。

【讨论】:

【解决方案2】:

OP 似乎对变通方法不感兴趣。无论如何,这是我的:

public static object InvokeCorrectly(this Control control, Delegate method, params object[] args) {
    Exception failure = null;
    var result = control.Invoke(new Func<object>(() => {
        try {
            return method.DynamicInvoke(args);
        } catch (TargetInvocationException ex) {
            failure = ex.InnerException;
            return default;
        }
    }));
    if (failure != null) {
        throw failure;
    }
    return result;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-12-22
    • 2010-11-22
    • 1970-01-01
    • 2013-09-02
    • 2015-12-25
    • 1970-01-01
    • 2013-10-07
    相关资源
    最近更新 更多