当我的BroadcastBlock发布时,为什么我的ActionBlock没有被执行?

时间:2018-06-08 13:59:57

标签: c# multithreading dataflow

我正在尝试理解C#中的Dataflow,所以我写了一个小提琴here,我很好奇为什么我的动作块没有在我的例子中执行。

using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;

public class Program
{
    public static void Main(string[] args)
    {
        var numberOfProducers = 1;
        var numberOfConsumers = 10;

        var allProducers = Enumerable.Range(0, numberOfProducers).Select(x => new BroadcastBlock<double>(d =>
            {
                return d;
            },
            new DataflowBlockOptions()
            {
                BoundedCapacity = 500
            }));

        var allConsumers = Enumerable.Range(0, numberOfConsumers).Select(x => new ActionBlock<double>(d =>
            {
                Console.WriteLine(String.Format("Consuming {0} on Thread ID: {1}", d, Thread.CurrentThread.ManagedThreadId));
            },
            new ExecutionDataflowBlockOptions()
            {
                BoundedCapacity = 500
            }));

        foreach (var producer in allProducers)
        {
            foreach (var consumer in allConsumers)
            {
                producer.LinkTo(consumer);
            }
        }

        Parallel.For(0, 20, (i) =>
        {
            foreach (var producer in allProducers)
            {
                Console.WriteLine(String.Format("Posting {0} on Thread ID: {1}", i, Thread.CurrentThread.ManagedThreadId));
                producer.Post(i);
            }
        }

        );
    }
}

该程序的输出示例如下

  

在线程ID上发布0:18

     

在主题ID上发布10:16

     

在主题ID上发布1:17

     

在主题ID上发布11:19

     

在主题ID上发布2:18

     

在线程ID上发布4:17

     

在线程ID上发布5:17

     

在线程ID上发布6:17

     

在主题ID上发布3:18

     

在主题ID上发布12:18

     

在线程ID上发布7:17

     

在线程ID上发布16:19

     

在线程ID上发布8:17

     

在线程ID上发布17:19

     

在线程ID上发布9:17

     

在帖子ID上发布18:19

     

在主题ID上发布19:19

     

在主题ID上发布13:18

     

在主题ID上发布14:18

     

在主题ID上发布15:18

我希望在显示动作块消耗广告块上发布的数据时会混合多行。

1 个答案:

答案 0 :(得分:0)

延迟评估是动作块未被执行的原因。

allProducersallConsumers是惰性评估的,因此每次枚举时都会生成新的生产者和新的消费者。因此,producer.LinkTo(consumer)中引用的生成器与producer.Post(i)

中引用的生成器不同

我在调试器中单步执行代码时意识到了这一点,当暂停在producer.Post(i)时,它显示当前在范围内的生产者有0个与之关联的目标。

解决方案是将ToListToArray添加到allProducersallConsumers

的定义中
var allProducers = Enumerable.Range(0, numberOfProducers).Select(x => new BroadcastBlock<double>(d =>
        {
            return d;
        })).ToList();

var allConsumers = Enumerable.Range(0, numberOfConsumers).Select(x => new ActionBlock<double>(d =>
        {
            Console.WriteLine($"Consuming {d} on Thread ID: {Thread.CurrentThread.ManagedThreadId}"); ;
        })).ToList();