检查队列<t>连续</t>

时间:2011-04-21 04:11:53

标签: c# .net multithreading thread-safety

我想要一个函数在一个线程上连续检查队列中的新添加

显然可以选择连续循环播放睡眠,但我希望减少浪费。

我考虑了某种类型的等待句柄,然后让队列发出信号,但我无法安全地覆盖Enqueue,因为它不是虚拟的。

现在我正在考虑将Queue<T>封装成我最好的选择,但是如果有更好的选择,我想问问好人们吧!

我的想法是:我希望许多线程访问套接字连接,同时保证它们只读取其消息的响应,因此我将有一个线程调度和读取响应,然后使用响应数据执行回调(在纯文本)

1 个答案:

答案 0 :(得分:17)

尝试阻止队列:Creating a blocking Queue<T> in .NET?

基本思路是,当你调用TryDequeue时,它会阻塞,直到队列中有东西为止。你可以看到阻塞队列的“美丽”是你不必轮询/睡觉或做任何疯狂的事情......它是制作人/消费者模式的基本支柱。

我的阻塞队列版本是:

public class BlockingQueue<T> where T : class
{
    private bool closing;
    private readonly Queue<T> queue = new Queue<T>();

    public int Count
    {
        get
        {
            lock (queue)
            {
                return queue.Count;
            }
        }
    }

    public BlockingQueue()
    {
        lock (queue)
        {
            closing = false;
            Monitor.PulseAll(queue);
        }
    }

    public bool Enqueue(T item)
    {
        lock (queue)
        {
            if (closing || null == item)
            {
                return false;
            }

            queue.Enqueue(item);

            if (queue.Count == 1)
            {
                // wake up any blocked dequeue
                Monitor.PulseAll(queue);
            }

            return true;
        }
    }


    public void Close()
    {
        lock (queue)
        {
            if (!closing)
            {
                closing = true;
                queue.Clear();
                Monitor.PulseAll(queue);
            }
        }
    }


    public bool TryDequeue(out T value, int timeout = Timeout.Infinite)
    {
        lock (queue)
        {
            while (queue.Count == 0)
            {
                if (closing || (timeout < Timeout.Infinite) || !Monitor.Wait(queue, timeout))
                {
                    value = default(T);
                    return false;
                }
            }

            value = queue.Dequeue();
            return true;
        }
    }

    public void Clear()
    {
        lock (queue)
        {
            queue.Clear();
            Monitor.Pulse(queue);
        }
    }
}

非常感谢Marc Gravell这个!