多个生产者单个消费者锁定模式

时间:2015-12-13 20:08:33

标签: c# multithreading

我有多个生产线程,单一消费。在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();
}

我试过这个,但有一些机会,那个

  1. 主题B无法从_eventQueue
  2. 读取
  3. 线程A写入_eventQueue
  4. 线程A设置信号
  5. 线程B重置信号
  6. 主题B无限期等待
  7. 如何克服这个?以前,我使用了lock()Monitor.Wait()AutoResetEvent可能有所帮助(它会在成功Wait时重置),但不支持CancellationToken

1 个答案:

答案 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方法,那么一旦没有更多项目,就会完成消费可枚举。

这个类完全是线程安全的。