2011-08-17 8 views
4

私は、例外を伴う制御フローは悪い習慣と考えられていました。あなたは同じように簡単にcatchcommand.Execute()内部の例外が、私はここに欠けている何かが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); 

がある可能性があり:

は、それではなぜこのような何かをしますか?タスクは実行中のコードと無関係に例外をスローできますか?

EDIT: いかが我々は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

あなたのご意見に感謝します。 2番目の例の考えは? –

+1

成功したコールバック、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

関連する問題