2009-12-21 3 views
0

Сегодня я получил here nice answer, который разрешит мою проблему. К сожалению, я забыл спросить, как насчет блокировки.Запирание, вопрос qeue

Проблема была простой: на сервере каждый подключенный клиент получит уникальный идентификатор (многоразовый) от 1 до 500, который является максимальным для клиентов.

Ответ должен был создать qeue и использовать элементы ожидания для новых подключений и просто вернуть их обратно, когда они будут выпущены.

Я не уверен, правильно ли я понимаю - также я должен инициализировать qeue 500 элементами (ints) и просто взять их один за другим и вернуться назад после выхода?

Если да, то как насчет блокировки здесь, мой вопрос в основном был направлен на производительность, потому что я использовал блокировку.

ответ

1

Если вы можете использовать Parallel Extensions пойти на ConcurrentQueue

Если вы не можете найти, как реализовать свой собственный в this article Херб Саттер

Кстати, ответ Джон Скит говорит вы просто пытаетесь выполнить unqueue и, если пустое генерировать и использовать. Когда вы закончите с id, просто верните его, запустив его. Нет ссылки на 500 идентификаторов. ЕСЛИ вам нужно ограничить до 500 идентификаторов, вам нужно будет инициализировать очередь с вашими 500 идентификаторами, а затем вместо генерации новых BLOCK, когда очередь пуста. Для этого лучше подходит consumer/producer pattern.

+0

Таким образом, достаточно простого замка. – Thomas

+0

+1 w/Малая модификация ... BLOCKING - это только одно решение проблемы приложения, что делать, когда больше нет доступных соединений. В зависимости от системы и контекста вы можете захотеть вернуть код ошибки или исключить исключение (или любую другую парадигму обработки ошибок, которая уместна). Отличный ответ. – James

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(); 
     } 
    } 
} 
Смежные вопросы