2014-03-14 58 views
1

我對C#很新,並開始玩TPL今天。我決定寫一個修改版本的 任務任務。當所有作爲練習。我想它有以下行爲:編寫一個Task.WhenAll/When任何取消所有其他任務在第一次故障/取消任務

  • 當發現出現了故障或者被取消的第一個任務,取消,而不是等待他們完成任務的其餘部分。
  • 如果任務出現故障,返回的任務應該有正確的例外設定(通過連續即無吞嚥與OperationCancelledException替換())
  • 方法簽名沒有異步(想避免起泡它)。

我想出了下面一段不起作用的瘋狂/愚蠢的代碼,我很難想象發生了什麼。我無法想象會發生任何阻塞,我想象中發生的是一連串的任務,每個任務都等待其餘的完成。有人可以解釋發生了什麼嗎?

我不會在生產代碼中,這只是測試我的基本面。我認識到一個更簡單的方法是做一個Task.WhenAll,並讓列表中的任務本身具有延遲,以便在失敗時執行取消。

public static Task WhenAllError(List<Task> tasks, CancellationToken ct) 
    { 
     var tcs = new TaskCompletionSource<object>(); 
     return Task.WhenAny(tasks).ContinueWith<Task>((t) => 
      { 
       if (tasks.Count == 0) 
       { 
        tcs.SetResult(null); 
        return tcs.Task; 
       } 

       if (t.IsFaulted) 
       { 
        Console.WriteLine("Task faulted. Cancelling other tasks: {0}", t.Id); 
        cts.Cancel(); 
        // Make sure the tasks are cancelled if necessary 
        tcs.SetException(t.Exception); 
        return tcs.Task; 
       } 
       // Similarly handle Cancelled 

       tasks.Remove(t); 
       return WhenAllError(tasks, ct); 
      }).Unwrap(); 
    } 

回答

2

CancellationToken類沒有Cancel方法。您需要CancellationTokenSource才能取消CancellationToken

同樣影響任務的結果你需要一個TaskCompletionSource你不能安全地取消已經運行的任務 。看到這個post

+0

是的,我知道:)。因此,名稱cts/ct。我沒有包含那部分代碼。你也不能放棄已經完成的任務,但是你當然可以取消並等待任務被取消(因此評論如下:「//確保任務在必要時被取消」。 – Panther

+0

我正在尋找關於如何解釋任務本身是否正在計劃,運行,等待等等?是否存在阻塞?用戶有一個對代理任務(解包)的引用,並假設他在等待它,將創建的作爲結果的任務會發生什麼?還必須等待所有這些?或者將最後一個任務的完成跨越任務傳播到用戶正在等待的最外層任務? – Panther