2011-01-25 8 views
4

私のアプリケーションでタスク並列ライブラリを使用しています。私はタスク(それを "DoSomething"と呼ぶ)を取り消すことがあります。タスクにフォルトが発生しているか、キャンセルされているか、または正常に完了しているかにかかわらず、私はそのクリーンアップを実行するタスクに接続しています。タスクのキャンセルステータスを継続タスクに伝播する方法

このタスクを起動するコードでは、ステータス(フォルト、キャンセル、完了までの実行)がDoSomethingタスクのステータスを反映するTaskオブジェクトを返したいと思いますが、このタスクが返されるのは重要です継続タスクが実行されるまで

はここに例を示します

public Task Start(CancellationToken token) 
{ 
    var doSomethingTask = Task.Factory.StartNew(DoSomething 
               , token); 

    var continuationTask = doSomethingTask.ContinueWith 
       (
       (antecedent) => 
        { 
         if (antecedent.IsFaulted || antecedent.IsCanceled) 
         { 
          //Do failure-specific cleanup 
         } 

    //Do general cleanup without regard to failure or success 
         } 
       ); 

//TODO: How do I return a Task obj which Status reflect the status of doSomethingTask, 
//but will not transition to that status until continuationTask completes? 
} 

私はTaskCompletionSourceを使用することができ、それは場しのぎようです。他のアイデア?

+0

答えを投稿しましたが、ヒッチがありました。私は間もなくしなければならないより正確な解決策に取り組んでいます。 –

+0

申し訳ありません...質問時間:返されたタスクを待つ必要がありますか? –

+0

はい。返されたタスクは、元のタスクの状態を反映する必要があります。これには、そのタスクの実行が完了するまでのブロックが含まれます。 – anelson

答えて

7

このシナリオでは実際にはTaskCompletionSourceが理想だと思います。私。作業完了のシグナルとしてTaskを返そうとしていますが、そのタスクがステータスを報告する時期と方法を手動で制御しています。唯一の本当の注意点は、あなたがこれを行うことができないということです

var doSomethingTask = Task.Factory 
    .StartNew<object>(DoSomething, token) 
    .WithCleanup(Cleanup); 

public static Task<T> WithCleanup<T>(this Task<T> t, Action<Task<T>> cleanup) { 
    var cleanupTask = t.ContinueWith(cleanup); 
    var completion = new TaskCompletionSource<T>(); 
    cleanupTask.ContinueWith(_ => { 
     if(t.IsCanceled) { 
      completion.SetCanceled(); 
     } else if(t.IsFaulted) { 
      completion.SetException(t.Exception); 
     } else { 
      completion.SetResult(t.Result); 
     } 
    }); 
    return completion.Task; 
} 

とこのようにそれを呼び出す:あなたは簡単にこのような拡張メソッドで、このために必要なボイラープレートを隠すことができ平文の古い Taskは非汎用的なものがないので TaskCompletionSourceです。

+1

'Task 'は 'Task'を継承しているので、ジェネリックでない場合にジェネリックTCSを使うことができます。 – svick

関連する問題