2009-12-21 255 views
0

今天我得到了here nice answer這將解決我的問題。不幸的是,我忘了問如何鎖定。鎖定,問題問題

問題很簡單 - 在服務器中,每個連接的客戶端都會得到一個從1到500的唯一ID(可重用),這是最大的客戶端。

答案是創建一個qeue,併爲新連接使用等待元素,並在發佈時將其返回。

我不確定我是否理解正確 - 我也應該用500個元素(整數)初始化queue,並且一個接一個地返回,一旦發佈就返回?

如果是這樣,這裏鎖定什麼,我的問題主要是針對性能,因爲我使用鎖。

回答

1

如果你可以使用並行擴展走了ConcurrentQueue

如果你不能,你可以找到如何通過香草薩特

實現自己在this article順便說一句,在喬恩斯基特答案是告訴你只是嘗試去隊列,如果是空的生成和使用。當你完成一個id時,只需將它排入隊列即可。沒有提及500個ID。如果您需要限制到500個ID,那麼您將需要用500個ID來初始化隊列,然後在隊列爲空時,而不是生成新隊列。爲此,consumer/producer pattern將更適合。

+0

這麼簡單的鎖就夠了。 – Thomas 2009-12-21 16:29:31

+0

+1 w/Minor modification ... BLOCKING只是一個解決應用程序問題的方法,當沒有更多的連接可用時該怎麼做。根據系統和上下文,你可能想要返回一個錯誤代碼或拋出一個異常(或任何其他適當的錯誤處理範例)。優秀的答案否則。 – James 2009-12-21 16:31:38

0

我不明白你想做什麼。

您可以爲已用數字填充散列表。

而且您可以將其存儲在應用程序範圍內的變量中,並在訪問該資源時使用Application.Lock和Application.Unlock方法。

0

像這樣的東西?

/// <summary> 
/// Thread safe queue of client ids 
/// </summary> 
internal class SlotQueue 
{ 
    private readonly AutoResetEvent _event = new AutoResetEvent(false); 
    private readonly Queue<int> _items = new Queue<int>(); 
    private int _waitCount; 

    /// <summary> 
    /// Initializes a new instance of the <see cref="SlotQueue"/> class. 
    /// </summary> 
    /// <param name="itemCount">The item count.</param> 
    public SlotQueue(int itemCount) 
    { 
     // Create queue items 
     for (int i = 0; i < itemCount; ++i) 
      _items.Enqueue(i); 
    } 

    /// <summary> 
    /// Gets number of clients waiting in the queue. 
    /// </summary> 
    public int QueueSize 
    { 
     get { return _waitCount; } 
    } 

    /// <summary> 
    /// 
    /// </summary> 
    /// <param name="waitTime">Number of milliseconds to wait for an id</param> 
    /// <returns></returns> 
    public int Deqeue(int waitTime) 
    { 
     // Thread safe check if we got any free items 
     lock (_items) 
     { 
      if (_items.Count > 0) 
       return _items.Dequeue(); 
     } 

     // Number of waiting clients. 
     Interlocked.Increment(ref _waitCount); 

     // wait for an item to get enqueued 
     // false = timeout 
     bool res = _event.WaitOne(waitTime); 
     if (!res) 
     { 
      Interlocked.Decrement(ref _waitCount); 
      return -1; 
     } 

     // try to fetch queued item 
     lock (_items) 
     { 
      if (_items.Count > 0) 
      { 
       Interlocked.Decrement(ref _waitCount); 
       return _items.Dequeue(); 
      } 
     } 

     // another thread got the last item between waitOne and the lock. 
     Interlocked.Decrement(ref _waitCount); 
     return -1; 
    } 

    /// <summary> 
    /// Enqueue a client ID 
    /// </summary> 
    /// <param name="id">Id to enqueue</param> 
    public void Enqueue(int id) 
    { 
     lock (_items) 
     { 
      _items.Enqueue(id); 
      if (_waitCount > 0) 
       _event.Set(); 
     } 
    } 
}