Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/arduino/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何将任务异常定向到主线程?_C#_Task Parallel Library - Fatal编程技术网

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

C# 如何将任务异常定向到主线程?,c#,task-parallel-library,C#,Task Parallel Library,我正在Dispatcher.UnhandledException中处理所有异常,因此我尝试将来自任务的异常引导到此事件中|我试图在主线程中发送异常 task.ContinueWith((t) => { .... if (t.Exception != null) throw t.Exception; }, TaskScheduler.From

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

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

            }, TaskScheduler.FromCurrentSynchronizationContext());
但我不能在未处理的异常事件中接受此异常,我的解决方案有什么问题

更多信息,任务和延续正在WPF应用程序中使用MVVM Light的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
时,任务内的异常处理通常由以下过程处理:

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

  • 我开发了专门用于简化这些场景的。和方法包括对已取消和出错的先行任务的完整处理,这样您就不必在每次继续中检查先行任务的状态。
    选择
    然后
    方法(包括
    supportsErrors
    参数)可用于处理出现故障的任务(而不是将错误传播到父任务)。这些方法可用于处理已取消或出现故障的任务,同时仍将错误传播到父任务。

    如果可以将处理程序附加到父任务,则也会捕获这些异常。但是,请注意,这不一定在主线程上运行

     task.ContinueWith((t) =>
                {
                   ....
                   if (t.Exception != null)
                        throw t.Exception;
    
                }, TaskScheduler.FromCurrentSynchronizationContext());
    

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

    我找不到任何解释为什么会发生这种情况?!!!但为了解决我的问题,我使用了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());
            }
    

    TaskScheduler.FromCurrentSynchronizationContext()将在启动任务的线程的上下文中执行,该线程可能是主线程,也可能不是主线程。您是否已在主线程中订阅该线程:currentDomain.UnhandledException+=new UnhandledExceptionEventHandler(MyHandler)?在FromCurrentSynchronizationContext()上设置断点。当它中断时,使用Debug+Windows+线程查看它在哪个线程上运行。如果这不是主线程,那么它将不会像您希望的那样工作。我正在测试我的应用程序,然后我用一个更简单的版本更改了我的应用程序。仍然存在相同的问题,FromCurrentSynchronizationContext在UI线程上,但有些问题可能是我在这里做错了什么。我更新了我的question@duDE我使用了dispatcher Unhandled event App.Current.DispatcherUnhandledException
    UnobservedTaskeException
    在grabage Collection
    Task
    对象之后运行,因此您可能需要等待很长时间才能触发它。@ghord-这是一个很好的观点。在一个正在运行的应用程序中,在触发错误消息的事件发生后很长一段时间才报告错误消息,这真的很奇怪。非常混乱。