task.coninuewithvs c#中的数据流
本文关键字:数据流 coninuewithvs task | 更新日期: 2023-09-27 17:59:23
我已经开始学习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
看起来比数据流提供的冗长语法更简单。谁能澄清一下两者之间的区别吗。
数据流我用来创建一个compleax进程pipleins,流可以在其中分支、合并和循环。(你在这里展示的例子很简单)
Task.ContinueWith在一个更简单的代码中使用,当流只在一个函数列表中一个接一个地完成时。
使用您的代码,实际上没有什么区别。
但对于数据流来说,你做得不对——变换块有什么用,它总是只产生一个独立于输入的结果?
最好做一些处理。。。
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
可以使代码更简单、更可读。
您需要完全理解TPL Dataflow
的基础知识,因为现在您正在尝试做TPL Dataflow
管道本身可以轻松完成的事情:
df1.LinkTo(df2, new DataflowLinkOptions { PropagateCompletion = true });
现在,df1.Completion
不需要使用ContinueWith
,但您仍然需要通知df1
块(顺便说一句,命名很难看)(意外)完成,因为它不知道何时完成,与task:相比
df1.Post(2);
df1.Complete();
调用此方法将拒绝发送到df1
块的所有其他消息,在其缓冲区变空后,它将沿着管道传播完成消息,因此您只需等待它(同步或异步):
df2.Completion.Wait();
// or
await df2.Completion;
所以,基本上,区别在于任务只能运行一次,而块永远运行,直到你手动完成它。注意,你仍然可以继续块的Completion
任务:
df2.Completion.ContinueWith(t =>
{
// some other logic here
});