为什么当我的 BroadcastBlock 发布时我的 ActionBlock 没有被执行?
Why is my ActionBlock not executed when my BroadcastBlock posts?
我想了解 Dataflow in C#, so I wrote a fiddle 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);
}
}
);
}
}
该程序的输出示例如下
Posting 0 on Thread ID: 18
Posting 10 on Thread ID: 16
Posting 1 on Thread ID: 17
Posting 11 on Thread ID: 19
Posting 2 on Thread ID: 18
Posting 4 on Thread ID: 17
Posting 5 on Thread ID: 17
Posting 6 on Thread ID: 17
Posting 3 on Thread ID: 18
Posting 12 on Thread ID: 18
Posting 7 on Thread ID: 17
Posting 16 on Thread ID: 19
Posting 8 on Thread ID: 17
Posting 17 on Thread ID: 19
Posting 9 on Thread ID: 17
Posting 18 on Thread ID: 19
Posting 19 on Thread ID: 19
Posting 13 on Thread ID: 18
Posting 14 on Thread ID: 18
Posting 15 on Thread ID: 18
我希望在显示使用广播块上发布的数据的操作块时会有几行混在一起。
惰性评估是动作块未被执行的原因。
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();
我想了解 Dataflow in C#, so I wrote a fiddle 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);
}
}
);
}
}
该程序的输出示例如下
Posting 0 on Thread ID: 18
Posting 10 on Thread ID: 16
Posting 1 on Thread ID: 17
Posting 11 on Thread ID: 19
Posting 2 on Thread ID: 18
Posting 4 on Thread ID: 17
Posting 5 on Thread ID: 17
Posting 6 on Thread ID: 17
Posting 3 on Thread ID: 18
Posting 12 on Thread ID: 18
Posting 7 on Thread ID: 17
Posting 16 on Thread ID: 19
Posting 8 on Thread ID: 17
Posting 17 on Thread ID: 19
Posting 9 on Thread ID: 17
Posting 18 on Thread ID: 19
Posting 19 on Thread ID: 19
Posting 13 on Thread ID: 18
Posting 14 on Thread ID: 18
Posting 15 on Thread ID: 18
我希望在显示使用广播块上发布的数据的操作块时会有几行混在一起。
惰性评估是动作块未被执行的原因。
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();