. net 4.0任务:在Task.ContinueWith中重新抛出UI线程异常



我有一个WPF应用程序,在那里我使用System.Threading.Tasks进行长时间运行的WCF调用。我通过在Application.Current.DispatcherUnhandledException中添加处理程序来捕获未处理的异常。

我创建了一个任务,其中ContinueWith函数在UI线程上运行,使用以下代码:

var task = new Task<T>(func).ContinueWith(t =>
{
    if (t.IsFaulted)
    {
        throw t.Exception.GetBaseException();
    }
    else
    {
        // Show t.Result on UI
    }
}, TaskScheduler.FromCurrentSynchronizationContext());

当任务中发生异常时,我希望重新抛出异常,以便DispatcherUnhandledException处理程序可以处理它。但是,当我重新抛出异常时,如上所示,它会使我的应用程序崩溃,并且不会调用DispatcherUnhandledException。

如何在UI线程上重新抛出异常,以便调用DispatcherUnhandledException处理程序?

当我使用BackgroundWorker时,重新抛出异常正是这样做的。基本上,我希望用任务取代BackgroundWorker,因为任务有一些非常好的功能,我想利用。

解决这个问题的一种方法是在语句中包含的Lambda表达式中重新抛出Exception。比如:

Exception ex = t.Exception;
Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => { throw ex; }));

我不建议这样做,虽然它有点肮脏,但它确实回答了这个问题!

你也可以用SynchronizationContext.Post做类似的事情。

我有完全相同的问题,虽然在我的情况下,应用程序没有崩溃,但是,应用程序。DispatcherUnhandledException事件永远不会引发。我还尝试使用AppDomain.CurrentDomain.UnhandledException,这也不起作用。我喜欢有一个顶级异常处理程序来处理可能在许多地方发生的全局错误。

我开发了一个使用基于事件的异步模式(EAP)的库,我将其改为使用基于任务的异步模式(TAP),以准备。net 4.5,它具有更好的基于任务的异步支持。使用EAP,完成事件在UI线程上执行,这很好。使用任务,你必须像上面提到的那样使用TaskScheduler.FromCurrentSynchronizationContext()。我验证了ContinueWith代码在UI线程上运行,我从那里抛出异常。所以,我不知道发生了什么事。

希望这将在。net 4.5中得到修复,并希望现在从EAP切换到TAP不会为时过早。我喜欢用TAP可以更好地创作的事实。不过,不得不多次调用Dispatcher.Invoke()似乎有点糟糕。

最新更新