繁体   English   中英

如何将任务异常定向到主线程?

[英]how to direct task exception to main thread?

我正在Dispatcher.UnhandledException中处理所有异常,因此我尝试将来自Tasks的异常定向到此事件中。 |我试图在主线程中发送异常。

 task.ContinueWith((t) =>
            {
               ....
               if (t.Exception != null)
                    throw t.Exception;

            }, TaskScheduler.FromCurrentSynchronizationContext());

但是我无法在UnhandledException事件中接受此异常,我的解决方案出了什么问题?

更多信息 ,该任务和延续发生在使用MVVM Light的WPF应用程序中的RealyCommand中:这是我的测试视图模型, ExecuteTestCommand在UI线程中运行

 class MainViewModel : ViewModelBase
    {
        public MainViewModel()
        {
            App.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
        }

        void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            MessageBox.Show("got it");
            e.Handled = true;
        }
        #region TestCommand
        private RelayCommand _testCommand;
        public RelayCommand TestCommand
        {
            get
            {
                if (_testCommand == null)
                    _testCommand = new RelayCommand(ExecuteTestCommand, CanExecuteTestCommand);
                return _testCommand;
            }
        }
        private bool CanExecuteTestCommand()
        {
            return true;
        }
        private void ExecuteTestCommand()
        {
           // throw new Exception();

            Task.Factory.StartNew(() =>
                {

                }).ContinueWith(t =>
                {
                    App.Current.MainWindow.Title = "It is the main UI thread" + (App.Current.Dispatcher.Thread == System.Threading.Thread.CurrentThread).ToString();
                    throw new NotImplementedException();

                }, TaskScheduler.FromCurrentSynchronizationContext());
        }
        #endregion
} 

任务并行库的实现包括一个异常处理程序,该异常处理程序确保(在大多数情况下)任务中未处理的异常不会导致进程终止。 此处理程序意味着将永远不会调用您的UnhandledException事件。

当您不使用async / await ,通常通过以下过程来处理任务中的异常:

  1. 如果您的任务实际上是“封闭”任务的子任务,则“封闭”任务要么传播该异常,要么直接处理该异常(通过以下步骤)。
  2. 如果代码需要处理异常,则通常会注册一个延续,以检查进入Faulted状态的先前任务,并执行适当的操作(例如将错误直接报告给某种形式的处理程序)。

我开发了Rackspace线程库,专门用于简化这些情况。 Select and Then方法包括对已取消和有故障的前提任务的完整处理,因此您不必在每个后续操作中都检查前提条件的状态。 包含supportsErrors参数的Select and Then方法可用于处理错误的任务(并且不会将错误传播给父对象)。 Finally方法可用于处理已取消或出现故障的任务,同时仍将错误传播给父级。

如果您可以将处理程序附加到TaskScheduler.UnobservedTaskException,您也将捕获这些异常。 但是,请注意,这不一定要在您的主线程上运行。

如果需要在主线程上处理异常,则可以在处理程序中添加代码以封送处理到主线程(然后重新抛出)。

我找不到任何解释为什么会发生这种情况?! 但是为了解决我的问题,我使用了Dispatcher.Invoke

 private void ExecuteTestCommand()
        {
           // throw new Exception();

            Task.Factory.StartNew(() =>
                {

                }).ContinueWith(t =>
                {
                     if (t.Exception != null)
                   {
                       App.Current.Dispatcher.Invoke(new Action(() =>
                       {
                           throw t.Exception;
                       }));
                       return;
                   }

                }, TaskScheduler.FromCurrentSynchronizationContext());
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM