2011-04-21 46 views
12

我想一个函数来检查队列为新增加连续在一个线程检查队列<T>不断

显然有一个持续循环与休眠的选项,但我想少浪费的东西。

我认为某种类型的等待句柄和然后将具有队列信号,但我不能重写排队安全,因为它不是虚拟的。

现在我正考虑封装一个Queue<T>作为我的最佳选择,但我想问问好的人,如果有更好的人!

我的想法是:我想要许多线程访问套接字连接,同时保证它们只读取其消息的响应,所以我将有一个线程分派并读取响应,然后使用响应数据执行回调(以纯文本格式)

回答

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这一个!

+3

这个实现似乎我错了。如果我叫'TryDequeue'对空队列具有有限的超时't'它会返回'默认(T)'直接,不是吗?它应该等待至少放弃之前't'。 – qerub 2014-02-10 13:22:24

+0

TryDequeue(out T value,int timeout):timeout是一个int值,它与Monitor.Wait()所期望的值相匹配,但如果负数被指定为超时值,则Monitor.Wait()将抛出System.ArgumentOutOfRangeException。 if检查负超时的第二部分只是确保返回一个默认值而不是引发异常。 – 2017-08-30 13:47:59