Stack Трассировка исключений между потоками с помощью Invoke - PullRequest
1 голос
/ 30 марта 2010

Когда возникает исключение после вызова 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 ]

3 голосов
/ 30 марта 2010

Проверьте свойство InnerException исключения.

1 голос
/ 30 марта 2010

Да, это не идеально. Исключение перехватывается и повторно генерируется в потоке, который вызывает Invoke (). Обязательно отсутствуют кадры стека кода в потоке пользовательского интерфейса, они уже размотаны к тому моменту, когда исключение перезапускается. То, что оно не использует свойство InnerException, не очень хорошо.

Один из обходных путей - перехватить исключение в вызванном методе и сохранить его в закрытом поле. Лучше использовать BeginInvoke вместо Invoke. Это вызовет исключение непосредственно в потоке пользовательского интерфейса.

1 голос
/ 30 марта 2010

Если вы посмотрите на TargetSite на самом исключении, оно даст вам имя функции, которая была динамически вызвана (или получит метод, который вызвал текущее исключение):
Имя "BadFunction" Строка

Исключение содержит фактическое исключение, которое вы имеете из вызова: System.NullReferenceException {"Ссылка на объект не установлена ​​на экземпляр объекта."} System.Exception

Вот мой след стека: в WindowsApplication1.Form1.BadFunction () в C: \ Development \ Test \ WindowsApplication1 \ WindowsApplication1 \ Form1.vb: строка 35 в WindowsApplication1.Form1.UpdateStuff () в C: \ Development \ Test \ WindowsApplication1 \ WindowsApplication1 \ Form1.vb: строка 22 * ​​1008 *

1 голос
/ 30 марта 2010

попробуй ... поймать блок возможно.

0 голосов
/ 19 января 2017

Ганс упомянул два варианта. Шесть лет спустя есть третья, которая мне кажется удобной. Просто оберните ваш вызов в делегат, который может сохранить исключение в вашей локальной области, а затем используйте его:

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);
}
0 голосов
/ 28 января 2012

Выезд https://connect.microsoft.com/VisualStudio/feedback/details/386582/control-invoke-exception-handling который подробно описывает эту проблему и позволяет вам проголосовать за нее, чтобы команда Visual Studio могла снова включить ее в свой список приоритетов (в данный момент он помечен как «Не исправлять»).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...