【发布时间】:2011-09-23 11:19:34
【问题描述】:
我正在使用 .NET 4.0 BlockingCollection 来处理一个项目队列,每个项目都需要由一个操作处理,该操作可能需要一秒钟来处理每个项目。这个项目队列可以由不同的线程添加。
我对此有几个问题 a) 允许多个消费者处理此 BlockingCollection?我注意到 GetConsumingEnumerable(),它似乎适用于单一消费者场景。有多个消费者的原因是通过命名管道实例的处理一次最多可以处理三个这样的项目,所以我想我可以有三个消费者。
b) 有没有办法检查一个项目是否在这个队列中,如果是,让调用者检查是否有一个项目要阻塞,直到项目被处理?
编辑:
根据 Jon Skeet 的回答,这里有一些示例代码来说明多个消费者作用于由单个生产者填充的 BlockingCollection,消费者使用 GetConsumingEnumerable():
static BlockingCollection<string> coll = new BlockingCollection<string>();
static void Consume()
{
foreach (var i in coll.GetConsumingEnumerable())
{
Console.WriteLine(String.Format("Thread {0} Consuming: {1}", Thread.CurrentThread.ManagedThreadId, i));
Thread.Sleep(1000);
}
}
static void Main(string[] args)
{
int item = 0;
Task.Factory.StartNew(() =>
{
while (true)
{
coll.Add(string.Format("Item {0}", item++));
Thread.Sleep(500);
}
});
for (int i = 0; i < 2; i++)
{
Task.Factory.StartNew(() => Consume());
}
while (true) ;
}
项目在两个不同线程上运行的两个消费者之间以交错方式处理,例如
Thread 4 Consuming: Item 0
Thread 5 Consuming: Item 1
Thread 4 Consuming: Item 2
Thread 5 Consuming: Item 3
Thread 4 Consuming: Item 4
【问题讨论】:
-
当使用
GetConsumingEnumerable时,生产者调用CompleteAdding()以便消费者知道何时停止是很重要的。