简体   繁体   中英

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. |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?

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

 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.

When you are not using async / await , handling exceptions within a task is generally handled by the following process:

  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).

I developed the Rackspace Threading Library specifically for simplifying these scenarios. 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. 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). The Finally methods can be used to handle a canceled or faulted task while still propagating the error to the parent.

If you can attach a handler to TaskScheduler.UnobservedTaskException you'll catch these exceptions too. 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

 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());
        }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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