2011-01-25 61 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

發表了一個答案,但有一個順利。研究一個更加正確的解決方案,我很快就會有這個解決方案。 – 2011-01-28 17:38:17

+0

好的......問題時間:你需要等待()返回的任務嗎? – 2011-01-28 18:10:20

回答

7

我認爲TaskCompletionSource實際上是這種情況下的理想選擇。即您試圖返回Task作爲完成工作的信號,但手動控制任務何時以及如何報告其狀態。你可以很容易隱藏與擴展方法是這樣要求這個鍋爐板:

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; 
} 

,並調用它像這樣:

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

唯一真正需要注意的是,你不能做到這一點普通舊Task因爲沒有非通用TaskCompletionSource