我很难理解BlockingCollection
。
以下代码来自old answer,但它使用了两个队列。
using System;
using System.Collections.Concurrent;
using System.Threading;
using System.Threading.Tasks;
namespace Demo
{
class Program
{
static void Main(string[] args)
{
new Program().run();
}
void run()
{
int threadCount = 4;
Task[] workers = new Task[threadCount];
Task.Factory.StartNew(consumer);
for (int i = 0; i < threadCount; ++i)
{
int workerId = i;
Task task = new Task(() => worker(workerId));
workers[i] = task;
task.Start();
}
for (int i = 0; i < 100; ++i)
{
Console.WriteLine("Queueing work item {0}", i);
inputQueue.Add(i);
Thread.Sleep(50);
}
Console.WriteLine("Stopping adding.");
inputQueue.CompleteAdding();
Task.WaitAll(workers);
outputQueue.CompleteAdding();
Console.WriteLine("Done.");
Console.ReadLine();
}
void worker(int workerId)
{
Console.WriteLine("Worker {0} is starting.", workerId);
foreach (var workItem in inputQueue.GetConsumingEnumerable())
{
Console.WriteLine("Worker {0} is processing item {1}", workerId, workItem);
Thread.Sleep(100); // Simulate work.
outputQueue.Add(workItem); // Output completed item.
}
Console.WriteLine("Worker {0} is stopping.", workerId);
}
void consumer()
{
Console.WriteLine("Consumer is starting.");
foreach (var workItem in outputQueue.GetConsumingEnumerable())
{
Console.WriteLine("Consumer is using item {0}", workItem);
Thread.Sleep(25);
}
Console.WriteLine("Consumer is finished.");
}
BlockingCollection<int> inputQueue = new BlockingCollection<int>();
BlockingCollection<int> outputQueue = new BlockingCollection<int>();
}
}
我可以只使用一个队列吗?如果使用.net 4.5(TPL)替换它,我该怎么办?
答案 0 :(得分:2)
Producer-consumer是一个定义两个角色的模型:
组织互操作有不同的方法,但最简单的方法是Queue - 生产者将新项目排入其中,消费者将它们排队。
上面显示的代码示例实际上包含三个actor和两个队列:
制片人1(在主页中)
for (int i = 0; i < 100; ++i)
{
Console.WriteLine("Queueing work item {0}", i);
inputQueue.Add(i);
Thread.Sleep(50);
}
消费者1和生产者2同时(工人方法):
foreach (var workItem in inputQueue.GetConsumingEnumerable())
{
Console.WriteLine("Worker {0} is processing item {1}", workerId, workItem);
Thread.Sleep(100); // Simulate work.
outputQueue.Add(workItem); // Output completed item.
}
消费者2(消费者方法):
foreach (var workItem in outputQueue.GetConsumingEnumerable())
{
Console.WriteLine("Consumer is using item {0}", workItem);
Thread.Sleep(25);
}
这不是生产者 - 消费者 - 它是由两个连续生产者 - 消费者系统组织的传送带“模式”。
所以,答案:
不,不需要使用两个队列。您可以将示例缩减为适当的单级生产者 - 使用者,只需删除worker
方法并在inputQueue上使用consumer
方法操作。
关于old answer:
旧问题不涉及生产者 - 消费者 - 它涉及输送机模型 - 数据流。简单的生产者 - 消费者不需要任何复杂的多级数据转换。