2011-04-21 65 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