.net – 为什么例外不会被WPF Dispatcher.Invoke传播?

这是我的假设例子.我有一个非常简单的 WPF窗口与一个按钮. Button.Click事件有一个这样的处理程序.

Action doit = () =>
{
    Action error = () => { throw new InvalidOperationException("test"); };

    try {
        this.Dispatcher.Invoke(error, DispatcherPriority.Normal);
    } catch (Exception ex) {
        System.Diagnostics.Trace.WriteLine(ex);
        throw;
    }
};
doit.BeginInvoke(null, null);

我会期望这个异常会被Trace.WriteLine调用捕获和写入.相反,没有异常被捕获并且应用程序中断.

有人知道有可能解释这个吗?为了捕获由Dispatcher.Invoke调用的委托抛出的异常,您建议使用什么解决方法?

更新1:我抛出异常处理代码.我不想真正地忽略异常.我的问题的全部要点是正确处理.问题是异常处理代码从不执行.

记住这是一个假设的例子.我的真实代码看起来不像这样.另外,假设我无法更改要调用的方法中的代码.

更新2:考虑这个类似的例子.而不是一个WPF窗口,我有一个Windows窗体窗口.它具有几乎完全相同的处理程序的按钮.唯一的区别在于调用代码.就这样

this.Invoke(error);

在Windows窗体中,执行异常处理代码.为什么有区别?

UPDATED:要观察另一个线程中的异常,您要使用任务,将其排队到调度程序线程(使用 TaskScheduler.FromCurrentSynchronizationContext),然后等待它:

var ui = TaskScheduler.FromCurrentSynchronizationContext();
Action doit = () => 
{ 
    var error = Task.Factory.StartNew(
        () => { throw new InvalidOperationException("test"); },
        CancellationToken.None,
        TaskCreationOptions.None,
        ui); 

    try { 
        error.Wait(); 
    } catch (Exception ex) { 
        System.Diagnostics.Trace.WriteLine(ex); 
    } 
}; 
doit.BeginInvoke(null, null);

UPDATED(再次):由于您的目标是可重用的组件,因此建议您转到基于任务的界面或基于SynchronizationContext(例如event-based asynchronous pattern)的其他内容,而不是将组件放在Dispatcher或ISynchronizeInvoke上.

基于调度程序的组件仅适用于WPF / Silverlight;基于ISynchronizeInvoke的组件仅适用于Windows窗体.基于SynchronizationContext的组件可以透明地与WPF或Windows Forms一起工作,并且(更多的工作)ASP.NET,控制台应用程序,Windows服务等.

基于事件的异步模式是基于SynchronizationContext的组件的旧推荐方式;它仍然在.NET 3.5代码.但是,如果您使用的是.NET 4,任务并行库更加灵活,干净,功能强大. TaskScheduler.FromCurrentSynchronizationContext在下面使用SynchronizationContext,并且是编写需要这种同步的可重用组件的新方法.

相关文章
相关标签/搜索