Почему мой ActionBlock не выполняется, когда мои сообщения BroadcastBlock? - PullRequest
0 голосов
/ 08 июня 2018

Я пытаюсь понять Поток данных в C #, поэтому я написал скрипку здесь , и мне любопытно, почему мои блоки действий не выполняются в моем примере.

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);
            }
        }

        );
    }
}

Пример вывода из этой программы следующий:

Публикация 0 в ID темы: 18

Публикация 10 в ID темы: 16

Публикация 1 в идентификаторе темы: 17

Публикация 11 в идентификаторе темы: 19

Публикация 2 в идентификаторе темы: 18

Публикация 4 в идентификаторе темы: 17

Проводка 5 в идентификаторе темы: 17

Проводка 6 в идентификаторе темы: 17

Проводка 3 в идентификаторе темы: 18

Проводка 12 в идентификаторе темы: 18

Проводка 7 в идентификаторе темы: 17

Проводка 16 в идентификаторе темы: 19

Проводка 8 в идентификаторе темы: 17

Проводка 17 в идентификаторе темы: 19

Проводка 9 в идентификаторе темы: 17

Проводка 18 в идентификаторе темы: 19

Проводка 19 в идентификаторе темы: 19

Проводка 13 в идентификаторе темы: 18

Публикация 14 на ID темы: 18

Публикация 15 в идентификаторе потока: 18

Я ожидаю, что несколько строк будут смешаны при отображении блоков действий, использующих данные, публикуемые в блоке широковещания.

1 Ответ

0 голосов
/ 09 июня 2018

Ленивая оценка - это то, почему блоки действия не выполняются.

allProducers и allConsumers оцениваются лениво, поэтому каждый раз, когда они перечисляются, создаются новые производители и новые потребители.Таким образом, производитель, на который ссылается producer.LinkTo(consumer), отличается от того, на который ссылается producer.Post(i)

. Я понял это при пошаговом выполнении кода в отладчике, а при паузе на producer.Post(i) это показывало, чток производителю, находящемуся в области действия, было привязано 0 целей.

Решение добавляет ToList или ToArray к определениям allProducers и allConsumers

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();
...