2016-07-30 50 views
1

我已經開始學習TPL Dataflow。我正在努力找到Task.ContinueWith和數據流之間的區別。以下是兩個具有相同目標的樣本代碼。首先用Task.ContinueWith以及後來的數據流完成。
下面是與Task.ContinueWithtask.continuewith vs dataflow in c#

var tk1 = Task.Run(() => 
{ 
    Console.WriteLine("Entered 1st Task"); 
    Thread.Sleep(3000); 
    return 2; 
}); 

tk1.ContinueWith((t) => 
{ 
    Console.WriteLine("Entered 2nd Task"); 
    Thread.Sleep(2000); 
    Console.WriteLine(t.Result); 
}); 

tk1.Wait(); 

實施例和下面是與數據流相同的完成

var df1 = new TransformBlock<int,int>(t => 
{ 
    Console.WriteLine("Entered 1st DF"); 
    Thread.Sleep(3000); 
    return 2; 
}); 

var df2 = new ActionBlock<int>(t => 
{ 

    Console.WriteLine("Entered 2nd Task"); 
    Thread.Sleep(2000); 
    Console.WriteLine(t); 
}); 

df1.LinkTo(df2); 

df1.Completion.ContinueWith(t => 
df2.Complete()); 

df1.Post(2); 

df2.Completion.Wait(); 

Task.ContinueWith看起來比冗長語法,數據流提供了簡單的。任何人都可以請澄清兩者之間的差異。

回答

0

數據流我用來創建一個可以處理pipleins的可執行文件,其中流可以分支,合併和循環。 (你在這裏展示的例子是簡單)

Task.ContinueWith是一個簡單的代碼中使用時,在短短的功能列表中的流動做了一個又一個。

1

隨着代碼,實際上沒有區別。

但是你在做數據流的錯誤 - 變換塊的用途是什麼,只有總是產生一個獨立於輸入的結果?

更好的做一些處理...

var df1 = new TransformBlock<int,int>(input => 
    { 
     Console.WriteLine("Entered 1st DF"); 
     Thread.Sleep(3000); 
     return input+1; 
    }); 

...然後你看到了差距:

Task.Run將只運行一次,但

df1.Post(2); 
df1.Post(5); 
df1.Post(27); 
df1.Post(-1); 

將通過所有運行您的數據流網格化並生成輸出。

和BTW:使用async/await而不是Task.ContinueWith可以使您的代碼更簡單,更具可讀性。

0

你需要充分了解的基礎知識爲TPL Dataflow,因爲現在你想要做的事情,可以很容易地通過TPL Dataflow管道本身來完成:

df1.LinkTo(df2, new DataflowLinkOptions { PropagateCompletion = true }); 

現在你不需要使用ContinueWithdf1.Completion,但你仍然需要通知df1塊(醜陋的命名,順便說一句)至(驚喜)complete,因爲它不知道什麼時候完成,與任務比較:

df1.Post(2); 
df1.Complete(); 

調用此方法會拒絕發送給df1塊中的所有其他消息,它的緩衝區成爲空後,它會傳播完成下來的管道,所以你只需要等待它(同步或異步):

df2.Completion.Wait(); 
// or 
await df2.Completion; 

所以,基本上,不同之處在於任務只能運行一次,與塊相比,它會一直運行,直到您手動完成它爲止。請注意,您仍然可以繼續執行Completion任務:

df2.Completion.ContinueWith(t => 
{ 
    // some other logic here 
});