我正在学习TPL数据流。我尝试创建一个示例,其中我发布了来自不同Task
的一些值,并期望结果返回到同一Task
以进一步处理它。但结果出了问题。以下是我的代码。让我知道我在做什么,以及如何解决它。
static void Main(string[] args)
{
var transBlock = new TransformBlock<int, int>
(
n =>
{
Thread.Sleep(1000);
return (n*2);
}
);
new Task(() =>
{
var result = transBlock.Post(2);
var val = transBlock.Receive();
Console.WriteLine(string.Format("double for 2 is {0}", val));
}).Start();
new Task(() =>
{
var result = transBlock.Post(3);
var val = transBlock.Receive();
Console.WriteLine(string.Format("double for 3 is {0}", val));
}).Start();
new Task(() =>
{
var result = transBlock.Post(4);
var val = transBlock.Receive();
Console.WriteLine(string.Format("double for 4 is {0}", val));
}).Start();
new Task(() =>
{
var result = transBlock.Post(5);
var val = transBlock.Receive();
Console.WriteLine(string.Format("double for 5 is {0}", val));
}).Start();
new Task(() =>
{
var result = transBlock.Post(6);
var val = transBlock.Receive();
Console.WriteLine(string.Format("double for 6 is {0}", val));
}).Start();
new Task(() =>
{
var result = transBlock.Post(7);
var val = transBlock.Receive();
Console.WriteLine(string.Format("double for 7 is {0}", val));
}).Start();
Console.ReadLine();
}
结果每次都有所不同,但一旦出现这样的结果:
double for 5 is 8
double for 4 is 6
double for 3 is 4
double for 2 is 10
double for 6 is 12
double for 7 is 14
答案 0 :(得分:3)
这不是TPL数据流的工作方式。
TPL Dataflow是一个actor框架。您创建一个块,您告诉它该做什么,您将项目发布到它中,它一个接一个地(可能同时)执行每个项目的操作,然后输出结果。如果您有多个块,那么您可以将它们链接在一起并形成一个管道。
该块不知道是谁将哪个项目发布到其中。没有理由期望将结果返回到匹配任务。
如果要跟踪输入和输出,可以一起返回输入和输出的元组:
var transBlock = new TransformBlock<int, Tuple<int,int>>(async n =>
{
await Task.Delay(1000)
return Tuple.Create(n, n * 2);
});
var tuple = transBlock.Receive();
Console.WriteLine(string.Format("double for {0} is {1}", tuple.Item1, tuple.Item2));
答案 1 :(得分:0)
我不知道TPL Dataflow
是否为FIFO,但即使 ,您的代码也会出现竞争条件。
考虑这两个:
new Task(() =>
{
var result = transBlock.Post(2);
var val = transBlock.Receive();
Console.WriteLine(string.Format("double for 2 is {0}", val));
}).Start();
new Task(() =>
{
var result = transBlock.Post(3);
var val = transBlock.Receive();
Console.WriteLine(string.Format("double for 3 is {0}", val));
}).Start();
这些任务可能会也可能不会在不同的线程上执行。但是,如果他们执行,则第二个任务可以发布3
,然后将上下文传递给第一个任务,该任务发布2
并接收3
。