在任务中捕获exception的最好方法是什么?
使用System.Threading.Tasks.Task<TResult> ,我必须pipe理可能抛出的exception。 我正在寻找最好的方法来做到这一点。 到目前为止,我创build了一个基类来pipe理.ContinueWith(...)调用中的所有未捕获的exception.ContinueWith(...) 
我想知道是否有更好的方法做到这一点。 或者即使这是一个很好的方法来做到这一点。
 public class BaseClass { protected void ExecuteIfTaskIsNotFaulted<T>(Task<T> e, Action action) { if (!e.IsFaulted) { action(); } else { Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() => { /* I display a window explaining the error in the GUI * and I log the error. */ this.Handle.Error(e.Exception); })); } } } public class ChildClass : BaseClass { public void DoItInAThread() { var context = TaskScheduler.FromCurrentSynchronizationContext(); Task.Factory.StartNew<StateObject>(() => this.Action()) .ContinueWith(e => this.ContinuedAction(e), context); } private void ContinuedAction(Task<StateObject> e) { this.ExecuteIfTaskIsNotFaulted(e, () => { /* The action to execute * I do stuff with e.Result */ }); } } 
	
有两种方法可以执行此操作,具体取决于所用语言的版本。
C#5.0及以上版本
 您可以使用async和await关键字来为您简化大量的工作。 
  async和await被引入语言,以简化使用任务并行库 ,防止您必须使用ContinueWith并允许您继续以自上而下的方式编程。 
 正因为如此,您可以简单地使用try / catch块来捕获exception,如下所示: 
 try { // Start the task. var task = Task.Factory.StartNew<StateObject>(() => { /* action */ }); // Await the task. await task; } catch (Exception e) { // Perform cleanup here. } 
 请注意,封装上述的方法必须使用async关键字,以便您可以使用await 。 
C#4.0及更低版本
 您可以使用从TaskContinuationOptions枚举中获取值的ContinueWith重载处理exception,如下所示: 
 // Get the task. var task = Task.Factory.StartNew<StateObject>(() => { /* action */ }); // For error handling. task.ContinueWith(t => { /* error handling */ }, context, TaskContinuationOptions.OnlyOnFaulted); 
  TaskContinuationOptions枚举的OnlyOnFaulted成员表示只有在先行任务抛出exception时才应执行continuation。 
 当然,您可以有多个电话ContinueWithclosures同一个前提,处理非例外情况: 
 // Get the task. var task = new Task<StateObject>(() => { /* action */ }); // For error handling. task.ContinueWith(t => { /* error handling */ }, context, TaskContinuationOptions.OnlyOnFaulted); // If it succeeded. task.ContinueWith(t => { /* on success */ }, context, TaskContinuationOptions.OnlyOnRanToCompletion); // Run task. task.Start(); 
您可以创build一些自定义任务工厂,这将生成embedded式exception处理处理的任务。 像这样的东西:
 using System; using System.Threading.Tasks; class FaFTaskFactory { public static Task StartNew(Action action) { return Task.Factory.StartNew(action).ContinueWith( c => { AggregateException exception = c.Exception; // Your Exception Handling Code }, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously ).ContinueWith( c => { // Your task accomplishing Code }, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously ); } public static Task StartNew(Action action, Action<Task> exception_handler, Action<Task> completion_handler) { return Task.Factory.StartNew(action).ContinueWith( exception_handler, TaskContinuationOptions.OnlyOnFaulted | TaskContinuationOptions.ExecuteSynchronously ).ContinueWith( completion_handler, TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously ); } }; 
您可以忘记在客户端代码中处理从该工厂生成的任务的exception处理。 同时你还可以等待这些任务的完成或使用他们在火与忘记风格:
 var task1 = FaFTaskFactory.StartNew( () => { throw new NullReferenceException(); } ); var task2 = FaFTaskFactory.StartNew( () => { throw new NullReferenceException(); }, c => { Console.WriteLine("Exception!"); }, c => { Console.WriteLine("Success!" ); } ); task1.Wait(); // You can omit this task2.Wait(); // You can omit this 
但是,如果说实话,我不确定你为什么要完成处理代码。 无论如何,这个决定取决于你的应用程序的逻辑。