【问题标题】:Checking a Queue<T> Continuously连续检查队列<T>
【发布时间】:2011-04-21 04:11:52
【问题描述】:

我想要一个函数来在一个线程上连续检查队列是否有新添加

显然可以选择带睡眠的连续循环,但我想要一些不那么浪费的东西。

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

现在我正在考虑封装 Queue&lt;T&gt; 作为我的最佳选择,但我想问你们这些好人是否有更好的选择!

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

【问题讨论】:

    标签: c# .net multithreading thread-safety


    【解决方案1】:

    尝试阻塞队列: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 的这个!

    【讨论】:

    • 这个实现对我来说似乎是错误的。如果我在具有有限超时t 的空队列上调用TryDequeue,它将直接返回default(T),不是吗?在放弃之前,它应该至少等待t
    • 在 TryDequeue(out T value, int timeout) 中:timeout 是一个 int,它与 Monitor.Wait() 所期望的匹配,但 Monitor.Wait() 如果为负数,则会抛出 System.ArgumentOutOfRangeException被指定为超时。 if 的第二部分检查是否有负超时,只是确保返回默认值而不是引发异常。
    猜你喜欢
    • 2012-05-09
    • 1970-01-01
    • 1970-01-01
    • 2020-06-24
    • 2019-05-31
    • 2016-01-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多