C# 多生产者单消费者锁定模式

C# 多生产者单消费者锁定模式,c#,multithreading,C#,Multithreading,我有多个生产线程和一个消费线程。在C#中,我使用了ConcurrentQueue来实现这一点 当队列为空时,如何正确地将使用者线程置于睡眠状态 ManualResetEventSlim signal; void WorkerThread(CancellationToken token) { while(!token.IsCancellationRequested) { object work; if (!_eventQueue.TryDequeue

我有多个生产线程和一个消费线程。在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();
}
我试过这个,但还是有机会的

  • 线程B无法从
    \u事件队列中读取
  • 线程A写入
    \u事件队列
  • 线程A设置信号
  • 线程B重置信号
  • 线程B无限期地等待
  • 如何克服这个问题?以前,我使用了
    lock()
    Monitor.Wait()
    AutoResetEvent
    可能会有所帮助(它会在成功等待时重置),但不支持
    CancellationToken

    。您可以使用该类支持多个生产者和单个消费者的情况

    创建类型为
    BlockingCollection
    的对象,如下所示:

    BlockingCollection<object> collection = new BlockingCollection<object>(); //You can have a specific type instead of object if you want
    
    collection.Add("value");
    
    消费者可以使用
    getconsumineGenumerable
    方法获取从集合中获取项目的
    IEnumerable
    。当没有更多项时,此类可枚举项将阻塞(等待更多项)。这种方法也适用

    如果调用该方法,则一旦没有更多项,消费枚举将完成


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

    为什么不使用它?@YacoubMassad,坦白地说,以前从未听说过。看起来它正是我所需要的,如果你把它作为一个答案,我会接受它。谢谢。如果您正在构建服务器端代码(如ASP.Net站点),也可以查看。
    foreach (var item in collection.GetConsumingEnumerable())
    {
        //Consume item
    }