我有多个生产线程,单一消费。在C#中,我正在使用ConcurrentQueue
。
当队列为空时,如何正确地将消费者线程置于休眠状态?
ManualResetEventSlim signal;
void WorkerThread(CancellationToken token)
{
while(!token.IsCancellationRequested)
{
object work;
if (!_eventQueue.TryDequeue(out work))
{
signal.Reset();
signal.Wait(token);
continue;
}
...
}
}
...
void Produce(object o)
{
_eventQueue.Enqueue(o);
signal.Set();
}
我试过这个,但有一些机会,那个
_eventQueue
_eventQueue
如何克服这个?以前,我使用了lock()
和Monitor.Wait()
。 AutoResetEvent
可能有所帮助(它会在成功Wait
时重置),但不支持CancellationToken
。
答案 0 :(得分:4)
您可以使用BlockingCollection类来支持多个生产者和单个消费者的情况。
像这样创建BlockingCollection
类型的对象:
BlockingCollection<object> collection = new BlockingCollection<object>(); //You can have a specific type instead of object if you want
生产者可以简单地调用Add
方法将项目添加到集合中,如下所示:
collection.Add("value");
消费者可以使用GetConsumingEnumerable
方法获取从集合中获取项目的IEnumerable<T>
。当没有更多项目时,这样的可枚举将阻止(等待更多项目)。此方法也supports cancellation。
foreach (var item in collection.GetConsumingEnumerable())
{
//Consume item
}
如果你调用CompleteAdding
方法,那么一旦没有更多项目,就会完成消费可枚举。
这个类完全是线程安全的。