task.continuewith vs c# 中的数据流
Posted
技术标签:
【中文标题】task.continuewith vs c# 中的数据流【英文标题】:task.continuewith vs dataflow in c# 【发布时间】:2016-12-05 04:41:56 【问题描述】:我已经开始学习TPL Dataflow
。我正在努力找出Task.ContinueWith
和数据流之间的区别。以下是具有相同目标的两个示例代码。首先是使用Task.ContinueWith
完成,然后是数据流。
下面是Task.ContinueWith
的例子
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
看起来比数据流提供的冗长语法简单。任何人都可以请澄清两者之间的区别。
【问题讨论】:
【参考方案1】:我用来创建复杂的处理管道的数据流,其中流可以分支、合并和循环。 (你在这里展示的例子很简单)
Task.ContinueWith 用在一个更简单的代码中,当流程在一个函数列表中一个接一个地完成时。
【讨论】:
【参考方案2】:使用您的代码,实际上没有区别。
但是您在数据流方面做错了 - 转换块有什么用,它总是只产生一个独立于输入的结果?
最好做一些处理...
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);
将全部通过您的数据流网格并产生输出。
顺便说一句:使用async
/await
而不是Task.ContinueWith
可以使您的代码更简单、更易读。
【讨论】:
【参考方案3】:您需要完全了解TPL Dataflow
的基础知识,因为现在您正在尝试做TPL Dataflow
管道本身可以轻松完成的事情:
df1.LinkTo(df2, new DataflowLinkOptions PropagateCompletion = true );
现在您不需要将ContinueWith
用于df1.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
);
【讨论】:
以上是关于task.continuewith vs c# 中的数据流的主要内容,如果未能解决你的问题,请参考以下文章
在 Task ContinueWith TaskScheduler.FromCurrentSynchronizationContext 的 ShowDialog 中打开表单时,应用程序会冻结