2015-03-02 2 views
1

Мне нужно создать общую очередь, которая может быть поставлена ​​в очередь моими несколькими производителями и отключена несколькими потребителями.Thread safe Queue <t> in C#

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

Итак, в настоящий вопрос, я понимаю, что состояние очереди может меняться между contains() и операцией очереди, например, проверка сокетов - это просто форма контроля ошибок, а не замена. Я сделал это так, потому что два потока производителей могут в противном случае подбрасывать ошибку, когда два из одного и того же идентификатора (идентифицированные GUID) пытаются и очереди, что в противном случае было бы другими объектными экземплярами qBit.

Вопрос в том, является ли это разумной реализацией? Я не вижу, чтобы он зашел в тупик, потому что все методы вернутся независимо от результата обработки qBit, и это позволяет мне несколько предотвратить некоторые из них.

Мысли и/или второй комплект глаз, пожалуйста?

public class tsQueue<t> 
{ 
    object syncLock = new object(); 
    private Queue<qBit<t>> Q = new Queue<qBit<t>>(); 
    List<t> contents = new List<t>(); 

    public qBit<t> deQueue() 
    { 
     lock (syncLock) 
     { 
      qBit<t> pop = Q.Dequeue(); 
      contents.Remove(pop.item); 
      return pop; 
     } 
    } 

    public void enQueue(qBit<t> push) 
    { 
     lock (syncLock) 
     { 
      contents.Add(push.item); 
      Q.Enqueue(push); 
     } 
    } 

    public bool contains(t check) { 
     lock (syncLock) 
     { 
      return contents.Contains(check); 
     } 
    } 

    public class qBit<t> 
    { 
     public bool flag { get; set; } 
     private t _item; 
     public t item { get { return _item; } } 

     public qBit(t item) 
     { 
      this._item = item; 
     } 
    } 
} 
+5

Вы смотрели 'ConcurrentQueue '? – phoog

+1

Это выглядит безопасным для меня потоком. @phoog Я хотел бы сравнить решение с обоими. В моем опыте иногда вручную блокировка объекта, не связанного с потоками, на самом деле быстрее, чем использование объекта, который является потокобезопасным (например, с использованием очереди с ConcurrentQueue). Но, я думаю, выбор между этими двумя должен быть специфичным для приложения. – phishfordead

+0

@phishfordead, если производительность является проблемой, да, нужно проверить и рассмотреть, какое решение выполняется быстрее. Библиотечные решения часто медленнее, чем ручные решения; библиотека нуждается в логике для решения условий, которые могут быть неактуальны для рассматриваемого случая использования. Но библиотечный код также, скорее всего, будет лучше проверен, чем ручной код, не говоря уже о более тщательном анализе. Таким образом, преимущества лучшей производительности (если действительно бенчмаркинг показывает лучшую производительность) следует сопоставить с затратами на тестирование и отладку для обеспечения правильности. – phoog

ответ

0

ConcurrentQueue - это поточно-безопасная реализация, которая делает именно то, что вам нужно. Это также определенно будет быстрее, чем ваш собственный код. Используйте этот link, чтобы увидеть исходный код реализации ConcurrentQueue.

+0

Я посмотрел на ConcurrentQueue , и были вопросы, которые у меня были об этом, здесь упоминается https://msdn.microsoft.com/en-us/library/dd997373%28v=vs.110%29.aspx Это сделало меня не таким certian, поэтому я стрелял по более длинному ручному методу, но более легко заглянул в него. Я не думаю, что производительность будет проблемой, это не крайняя высокая производительность, просто должно быть, безусловно, надежными. – Sabre