我正在处理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
}
答案 0 :(得分:1)
任务并行库的实现包括一个异常处理程序,它确保(在大多数情况下)任务中未处理的异常不会导致进程终止。此处理程序意味着永远不会调用您的UnhandledException
事件。
当您不使用async
/ await
时,处理任务中的异常通常由以下过程处理:
Faulted
状态的先行任务,并执行适当的操作(例如直接将错误报告给某个表单的处理程序) 我专门为了简化这些场景而开发了Rackspace Threading Library。 Select
和Then
方法包括对已取消和有缺陷的先前任务的完整处理,因此您无需在每个续集中检查前提的状态。包含Select
参数的Then
和supportsErrors
方法可用于处理出现故障的任务(而不会将错误传播给父级)。 Finally
方法可用于处理已取消或出现故障的任务,同时仍将错误传播给父级。
答案 1 :(得分:1)
如果您可以将处理程序附加到TaskScheduler.UnobservedTaskException,那么您也会捕获这些例外情况。但请注意,这并不一定在主线程上运行。
如果您需要来处理主线程上的异常,您可以在处理程序中添加代码以编组主线程(然后甚至重新抛出)。
答案 2 :(得分:0)
我找不到任何解释为什么会发生这种情况?!!!但为了解决我的问题,我使用了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());
}