2011-08-17 109 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