簡體   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