2011-08-17 110 views
4

我的印象是控制流量与例外被认为是一种不好的做法。TaskContinuationOptions.OnlyOnFaulted不考虑使用异常的流量控制?

那么,为什么会做这样的事情:

var task = Task.Factory 
      .StartNew(() => command.Execute()); 
task.ContinueWith(t => 
         { 
          // success callback 
         }, TaskContinuationOptions.OnlyOnRanToCompletion); 
task.ContinueWith(t => 
         { 
          Log.Error(string.Format("'{0}' failed.", command.GetType()), t.Exception); 
          // error callback 
         }, TaskContinuationOptions.OnlyOnFaulted); 

时,你可以很容易地catchcommand.Execute()的例外,是有我丢失的东西吗?任务可以抛出与它们正在执行的代码无关的异常吗?

编辑: 怎么样,如果我们使用C#5的asyncawait关键字,你会说,这将是更好的,还是捕捉到所有真的没有关系,如上面的例子?

public class AsyncFooCommand : AsyncCommandBase<Bar> 
{ 
    public override Bar Execute() 
    { 
     try 
     { 
      var bar = // Do something that can throw SpecificException 
      Successful = true; 
      return bar; 
     } 
     catch (SpecificException ex) 
     { 
      // Log 
     } 
    } 
} 
public static class AsyncCommandExecutor<T> 
{ 
    // NOTE: don't care about sharing this between instances. 
    // ReSharper disable StaticFieldInGenericType 
    private static readonly ILog Log = LogManager.GetLogger(typeof(Infrastructure.Commands.AsyncCommandExecutor<>)); 
    // ReSharper restore StaticFieldInGenericType 

    public static async Task<T> Execute(IAsyncCommand<T> command, Action<T> success = null, Action error = null) 
    { 

     var task = Task.Factory 
      .StartNew(() => 
      { 
       return command.Execute(); 
      }); 
     task.ContinueWith(t => Log.Error(string.Format("'{0}' failed, something terrible happened.", command.GetType()), t.Exception), 
      TaskContinuationOptions.OnlyOnFaulted); 

     T result = await task; 

     if (success != null && command.Successful) 
     { 
      success(result); 
     } 
     if (error != null && !command.Successful) 
     { 
      error(); 
     } 

     return result; 
    } 
} 
+1

“任务可以抛出与它们正在执行的代码无关的异常吗?”是的 - 如果某个任务的线程被另一个线程中止,则该任务可能会抛出ThreadAbortException异常。这与任务相关的代码无关。 –

+0

很高兴知道,感谢您的意见。对第二个例子有什么想法? –

+1

成功回调w/OnlyOnFaulted标志? – Henrik

回答

6

你当然可以也不需要延续。这只是一种不同的方法。

但是,如果你发现在任务异常,它运行到完成,到外面的世界任务看起来是成功,而不是失败。如果您有其他延续,如TaskContinuationOptions.OnlyOnRanToCompletion或其他此类选项,并且技术上未能执行命令(并且刚刚发现异常),那么该任务可能会继续运行,可能需要先行程序才能成功运行。这更多的是关于任务状态管理。

+0

请参阅这里的解释http://blogs.msdn.com/b/nikos/archive/2011/10/31/how-to-avoid-scary-problems-when-using-the-task-parallel-library.aspx( OnlyOnFaulted和NotOnFaulted) – SochiX