2016-07-30 51 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 
});