简体   繁体   English

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

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

I am handling all of my exceptions in Dispatcher.UnhandledException so I tried to direct exceptions coming from Tasks into this event. 我正在Dispatcher.UnhandledException中处理所有异常,因此我尝试将来自Tasks的异常定向到此事件中。 |I tried to send exception in the main thread. |我试图在主线程中发送异常。

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

            }, TaskScheduler.FromCurrentSynchronizationContext());

but I can not take this exception in UnhandledException event , what is wrong with my solution? 但是我无法在UnhandledException事件中接受此异常,我的解决方案出了什么问题?

More Info , the task and continuation is happening in a RealyCommand in WPF app using MVVM Light: here is my test view model, ExecuteTestCommand is running in UI thread 更多信息 ,该任务和延续发生在使用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
} 

The implementation of the Task Parallel Library includes an exception handler which ensures (in most cases) that unhandled exceptions within a task do not result in the process terminating. 任务并行库的实现包括一个异常处理程序,该异常处理程序确保(在大多数情况下)任务中未处理的异常不会导致进程终止。 This handler means your UnhandledException event will never be called. 此处理程序意味着将永远不会调用您的UnhandledException事件。

When you are not using async / await , handling exceptions within a task is generally handled by the following process: 当您不使用async / await ,通常通过以下过程来处理任务中的异常:

  1. If your task is actually a sub-task of an "enclosing" task, then the "enclosing" task either propagates the exception or handles it directly (by the steps below). 如果您的任务实际上是“封闭”任务的子任务,则“封闭”任务要么传播该异常,要么直接处理该异常(通过以下步骤)。
  2. If the code needs to handle exceptions, it generally registers a continuation which checks for the antecedent task entering the Faulted status, and performs an appropriate action (such as directly reporting the error to a handler of some form). 如果代码需要处理异常,则通常会注册一个延续,以检查进入Faulted状态的先前任务,并执行适当的操作(例如将错误直接报告给某种形式的处理程序)。

I developed the Rackspace Threading Library specifically for simplifying these scenarios. 我开发了Rackspace线程库,专门用于简化这些情况。 The Select and Then methods include complete handling for canceled and faulted antecedent tasks so you don't have to check the status of the antecedent in every continuation. Select and Then方法包括对已取消和有故障的前提任务的完整处理,因此您不必在每个后续操作中都检查前提条件的状态。 The Select and Then methods which include a supportsErrors parameter can be used to handle a faulted task (and not propagate the error to the parent). 包含supportsErrors参数的Select and Then方法可用于处理错误的任务(并且不会将错误传播给父对象)。 The Finally methods can be used to handle a canceled or faulted task while still propagating the error to the parent. Finally方法可用于处理已取消或出现故障的任务,同时仍将错误传播给父级。

If you can attach a handler to TaskScheduler.UnobservedTaskException you'll catch these exceptions too. 如果您可以将处理程序附加到TaskScheduler.UnobservedTaskException,您也将捕获这些异常。 However, note that this doesn't necessarily run on your main thread. 但是,请注意,这不一定要在您的主线程上运行。

If you need to handle the exception on your main thread you could add code in the handler to marshal to the main thread (and then even re-throw). 如果需要在主线程上处理异常,则可以在处理程序中添加代码以封送处理到主线程(然后重新抛出)。

I could not find any explanation why this happens?!!! 我找不到任何解释为什么会发生这种情况?! but to solve my problem I used Dispatcher.Invoke 但是为了解决我的问题,我使用了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