Creating a blocking Queue in .NET?

后端 未结 10 819
半阙折子戏
半阙折子戏 2020-11-22 01:14

I have a scenario where I have multiple threads adding to a queue and multiple threads reading from the same queue. If the queue reaches a specific size all threads<

10条回答
  •  隐瞒了意图╮
    2020-11-22 01:30

    That looks very unsafe (very little synchronization); how about something like:

    class SizeQueue
    {
        private readonly Queue queue = new Queue();
        private readonly int maxSize;
        public SizeQueue(int maxSize) { this.maxSize = maxSize; }
    
        public void Enqueue(T item)
        {
            lock (queue)
            {
                while (queue.Count >= maxSize)
                {
                    Monitor.Wait(queue);
                }
                queue.Enqueue(item);
                if (queue.Count == 1)
                {
                    // wake up any blocked dequeue
                    Monitor.PulseAll(queue);
                }
            }
        }
        public T Dequeue()
        {
            lock (queue)
            {
                while (queue.Count == 0)
                {
                    Monitor.Wait(queue);
                }
                T item = queue.Dequeue();
                if (queue.Count == maxSize - 1)
                {
                    // wake up any blocked enqueue
                    Monitor.PulseAll(queue);
                }
                return item;
            }
        }
    }
    

    (edit)

    In reality, you'd want a way to close the queue so that readers start exiting cleanly - perhaps something like a bool flag - if set, an empty queue just returns (rather than blocking):

    bool closing;
    public void Close()
    {
        lock(queue)
        {
            closing = true;
            Monitor.PulseAll(queue);
        }
    }
    public bool TryDequeue(out T value)
    {
        lock (queue)
        {
            while (queue.Count == 0)
            {
                if (closing)
                {
                    value = default(T);
                    return false;
                }
                Monitor.Wait(queue);
            }
            value = queue.Dequeue();
            if (queue.Count == maxSize - 1)
            {
                // wake up any blocked enqueue
                Monitor.PulseAll(queue);
            }
            return true;
        }
    }
    

提交回复
热议问题