使用Invoke堆栈跟踪跨线程异常

时间:2010-03-30 15:37:10

标签: .net multithreading exception

在调用Invoke之后发生异常时,.NET会显示堆栈跟踪,就像调用Invoke时发生错误一样。

以下示例:.NET将在UpdateStuff中发出错误而不是UpdateStuff - > BadFunction

有没有办法捕获“真正的”异常并显示正确的堆栈跟踪?

Private Sub UpdateStuff()

    If (Me.InvokeRequired) Then
        Me.Invoke(New UpdateStuffDelegate(AddressOf UpdateStuff))
        Return
    End If

    Badfunction()

End Sub

Private Sub BadFunction()

    Dim o As Object

    o.ToString()

End Sub

6 个答案:

答案 0 :(得分:3)

检查异常的InnerException属性。

答案 1 :(得分:1)

尝试......赶上阻挡。

答案 2 :(得分:1)

如果查看异常本身的TargetSite,它将为您提供动态调用的函数的名称(或者它获取引发当前异常的方法):
名称“BadFunction”字符串

该异常包含您从调用中获得的实际异常:System.NullReferenceException {“对象引用未设置为对象的实例。”} System.Exception

这是我的堆栈跟踪:    位于C:\ Development \ Test \ WindowsApplication1 \ WindowsApplication1 \ Form1.vb中的WindowsApplication1.Form1.BadFunction():第35行    位于C:\ Development \ Test \ WindowsApplication1 \ WindowsApplication1 \ Form1.vb中的WindowsApplication1.Form1.UpdateStuff():第22行

答案 3 :(得分:1)

是的,这不完美。在调用Invoke()的线程中捕获并重新抛出异常。必然,它缺少UI线程中代码的堆栈帧,它们在重新抛出异常时已经解开。它不使用InnerException属性并不是很好。

一种解决方法是在调用的方法中捕获异常并将其存储在私有字段中。更好的方法是使用BeginInvoke而不是Invoke。这将直接在UI线程中引发异常。

答案 4 :(得分:0)

结帐https://connect.microsoft.com/VisualStudio/feedback/details/386582/control-invoke-exception-handling 详细描述了这个问题,并允许您对其进行投票,以便Visual Studio团队可以再次将其置于优先级列表中(此时标记为“Not not Fix”)。

答案 5 :(得分:0)

汉斯提到了两个选择。六年后,有三分之一我觉得很方便。只需将您的调用包装在可以在本地范围内保留异常的委托中,然后使用它:

Exception exceptionFromDelegate = null;
formForSynchronizing.Invoke(new Action(() =>
{
    try
    {
        SomeMethod();
    }
    catch (Exception error)
    {
        exceptionFromDelegate = error;
    }
}));
if (exceptionFromDelegate != null)
{
    // with .net 4.5 you can do this:
    ExceptionDispatchInfo.Capture(exceptionFromDelegate).Throw();

    // otherwise maybe go straight to your error reporting system
    ReportException(exceptionFromDelegate);
}