Потокобезопасная буферизованная наблюдаемая приоритетная очередь? - PullRequest
5 голосов
/ 25 сентября 2010

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

Я хочу отобразить первые 100 элементов или около того в WPF DataGrid, поэтому к нему также должен обращаться поток пользовательского интерфейса. Было бы неплохо, если бы он мог уведомить поток пользовательского интерфейса о том, что также произошло обновление, то есть реализует IObservable.

Есть ли контейнерный класс, который будет делать все это?

Что касается бонусных баллов, я уверен, что не нужно блокировать всю очередь как при постановке, так и при снятии очереди.

.NET 4 реализации в порядке.

Ответы [ 3 ]

3 голосов
/ 25 сентября 2010

Вам не повезло в поисках контейнера - вы должны реализовать его самостоятельно. Будьте осторожны с приоритетами - сортировка идет медленно. Что я делаю, так это то, что у меня реализован класс очереди, который внутренне использует несколько массивов (по одному на каждый приоритет - кодированный низкий, средний, высокий). Таким образом, я никогда не сортирую. Избегайте блокировок, если вы можете (предполагается многоядерный), и используйте Spinlocks (.NET 4.0), они быстрее / несут меньше издержек в сценарии очереди.

2 голосов
/ 25 сентября 2010

То, что я делал в прошлом, заключено в несколько ConcurrentQueue<T> коллекций в одну - что-то, что TomTom предлагает .Это довольно разумно, когда число приоритетов, которые вы намереваетесь иметь, невелико.Например, в некоторых случаях может быть даже достаточно иметь два: высокий и низкий.Тогда ваш TryDequeue метод выглядит примерно так:

public bool TryDequeue(out T item)
{
    return _highItems.TryDequeue(out item) || _lowItems.TryDequeue(out item);
}

Это не совсем исчерпывающий ответ на ваш вопрос, но, возможно, он поможет вам начать работу.

2 голосов
/ 25 сентября 2010

Если вы работаете в .NET 4, вам следует серьезно рассмотреть возможность параллельной библиотеки задач с пользовательским планировщиком, как в примере QueuedTaskScheduler . Я не уверен, что он отвечает всем вашим требованиям, но это было бы хорошим началом.

...