使用System.Threading.Tasks.Task<TResult>,我必须管理可能引发的异常。我正在寻找做到这一点的最佳方法。到目前为止,我已经创建了一个基类,该基类在调用时管理所有未捕获的异常。.ContinueWith(...)
System.Threading.Tasks.Task<TResult>
.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 */ }); } }
有两种方法可以执行此操作,具体取决于您所使用的语言版本。
您可以使用async和await关键字为您简化很多操作。
async
await
async并且await被引入该语言以简化使用Task Parallel Library的工作,从而避免了您必须使用ContinueWith并允许您以自上而下的方式继续编程。
ContinueWith
因此,您可以简单地使用try/catch块来捕获异常,如下所示:
try
catch
try { // Start the task. var task = Task.Factory.StartNew<StateObject>(() => { /* action */ }); // Await the task. await task; } catch (Exception e) { // Perform cleanup here. }
请注意,封装上述内容的方法 必须 使用已async应用关键字,这样您才可以使用await。
您可以使用从枚举中获取值的ContinueWith重载来处理异常,如下所示:TaskContinuationOptions
TaskContinuationOptions
// Get the task. var task = Task.Factory.StartNew<StateObject>(() => { /* action */ }); // For error handling. task.ContinueWith(t => { /* error handling */ }, context, TaskContinuationOptions.OnlyOnFaulted);
在OnlyOnFaulted该成员TaskContinuationOptions枚举指示应继续 只 当先行任务抛出异常执行。
OnlyOnFaulted
当然,您可以有多个调用来ContinueWith取消同一先决条件,从而处理非例外情况:
// 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();