2015-02-26 4 views
4

Рассмотрим следующие два приложения:Почему Dispatcher.BeginInvoke распаковывает TargetInvocationException для ThreadStart, но не для Action?

1:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     this.Dispatcher.UnhandledException += Dispatcher_UnhandledException; 
    } 

    void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine(e.Exception.GetType()); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     this.Dispatcher.BeginInvoke((ThreadStart)delegate 
     { 
      throw new AccessViolationException("test"); 
     }, DispatcherPriority.Input); 
    } 
} 

2:

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     this.Dispatcher.UnhandledException += Dispatcher_UnhandledException; 
    } 

    void Dispatcher_UnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e) 
    { 
     System.Diagnostics.Debug.WriteLine(e.Exception.GetType()); 
    } 

    private void Button_Click(object sender, RoutedEventArgs e) 
    { 
     Dispatcher.BeginInvoke((Action)delegate 
     { 
      throw new AccessViolationException("test"); 
     }, DispatcherPriority.Input); 
    } 
} 

Оба приложения являются идентичными для использования двух различных типов делегата, Action и ThreadStart, за исключением (которые имеют тот же подпись).

Результаты (окно вывода, при вызове обработчика события с помощью кнопки мыши)

1: System.Reflection.TargetInvocationException

2: System.AccessViolationException

Почему приложения отличаются поведение?

Полный стек для исключения # 1:

System.Reflection.TargetInvocationException: Ein Aufrufziel hat einen Ausnahmefehler verursacht. ---> System.AccessViolationException: test 
    bei ExceptionTest.MainWindow.<Button_Click>b__0() in c:\Users\fschmitz\Documents\Visual Studio 11\Projects\ExceptionTest\MainWindow.xaml.cs:Zeile 40. 
    --- Ende der internen Ausnahmestapelüberwachung --- 
    bei System.RuntimeMethodHandle.InvokeMethod(Object target, Object[] arguments, Signature sig, Boolean constructor) 
    bei System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj, Object[] parameters, Object[] arguments) 
    bei System.Delegate.DynamicInvokeImpl(Object[] args) 
    bei System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Int32 numArgs) 
    bei MS.Internal.Threading.ExceptionFilterHelper.TryCatchWhen(Object source, Delegate method, Object args, Int32 numArgs, Delegate catchHandler) 
+0

так действительно ваш вопрос: «Почему« Displatcher.BeginInvoke (Action) «throw» и «AccessViolationException»? » – DLeh

+0

@ DLeh: Я думаю, что более подходящая формулировка «почему« Dispatcher.BeginInvoke »позаботится о том, чтобы развернуть« TargetInvocationException »для« Action », но не для« ThreadStart »? –

+0

@JeroenMostert Да, это тоже будет подходящим предметом. – floele

ответ

4

Я думаю, что преступник находится в пределах InternalRealCall метода ExceptionWrapper. В частности, следующая часть, в которой у нас есть Action делегатов, специализированных.

Action action = callback as Action; 
if (action != null) 
{ 
    action(); 
} 
else 
{ 
    // ... removed code .. 
    obj = callback.DynamicInvoke(); 
} 

С Action делегаты призваны непосредственно в результате Исключением является тот, который вы изначально выброшен. Для всех других типов делегатов, поскольку вызов проходит через отражение, исключение завершается в TargetInvocationException.

В заключение различия являются побочным эффектом, связанным с тем, как вызываемый делегат называется, непосредственно или через отражение.

+0

Следуя следнику стека, добавленному к вопросу, я смог точно определить этот код как возможный преступник. –

+0

Действительно, это имеет смысл, я полностью пропустил эту часть кода. Мои попытки отслеживания вызова всегда заканчивались на ExceptionFilterHelper, который не содержится в исходных источниках ... Я должен был посмотреть на метод, который вы разместили прямо: - \ В любом случае, спасибо! – floele

 Смежные вопросы

  • Нет связанных вопросов^_^