为什么Dispatcher.BeginInvoke为ThreadStart解包TargetInvocationException而不为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); } } 

除了使用两种不同的委托类型ActionThreadStart (虽然它们具有相同的签名)之外,两个应用程序都是相同的。

结果(输出窗口,当您使用按钮单击调用事件处理程序时)

1:System.Reflection.TargetInvocationException

2:System.AccessViolationException

为什么应用程序的行为不同?

例外#1的完整堆栈:

 System.Reflection.TargetInvocationException: Ein Aufrufziel hat einen Ausnahmefehler verursacht. ---> System.AccessViolationException: test bei ExceptionTest.MainWindow.

我认为罪魁祸首在于ExceptionWrapper InternalRealCall方法。 更具体地说,以下部分我们有Action代表特别套装。

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

由于Action委托直接调用,因此产生的exception是您最初抛出的exception。 对于所有其他委托类型,由于调用通过reflection,exception包含在TargetInvocationException

总之,差异是与直接或通过反思调用所提供的代表的方式相关的副作用。