我正在努力理解TPL Dataflow模块中的“完成(completion)”概念。特别是,TransformBlock
似乎从来没有完成过。为什么呢?
示例程序
我的代码计算了从1到1000的所有整数的平方。我使用了一个BufferBlock
和一个TransformBlock
。稍后在我的代码中,我等待TransformBlock
完成。但是该块实际上从未完成过,我不明白为什么。
static void Main(string[] args)
{
var bufferBlock = new BufferBlock<int>();
var calculatorBlock = new TransformBlock<int, int>(i =>
{
Console.WriteLine("Calculating {0}²", i);
return (int)Math.Pow(i, 2);
}, new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 8 });
using (bufferBlock.LinkTo(calculatorBlock, new DataflowLinkOptions { PropagateCompletion = true }))
{
foreach (var number in Enumerable.Range(1, 1000))
{
bufferBlock.Post(number);
}
bufferBlock.Complete();
// This line never completes
calculatorBlock.Completion.Wait();
// Unreachable code
IList<int> results;
if (calculatorBlock.TryReceiveAll(out results))
{
foreach (var result in results)
{
Console.WriteLine("x² = {0}", result);
}
}
}
}
一开始我以为自己创建了死锁,但事实并非如此。当我在调试器中检查calculatorBlock.Completion
任务时,它的Status
属性被设置为WaitingForActivation
。那一刻我的大脑死机了。
BufferBlock
并查看源代码。 - i3arnon