2010-10-17 5 views
2

Моя головная боль - мое серверное приложение превышает максимальное количество открытых подключений к базе данных во время загрузки. Итак, я полагаю, мне нужна очередь задач (ака сервисная шина) для доступа к базе данных для записи. Очередь, что запросы на запись в db могут быть отправлены на нее, а посвященные потоки будут читать и выполнять.Реализация очереди многопоточных задач в .NET.

Мне было интересно, есть ли готовые компоненты, которые делают именно это. Мои требования:

  1. Несколько потоков могут записываться в очередь с минимальной блокировкой.
  2. Более одного потока можно прочитать из очереди для выполнения отправленных запросов на запись. В наиболее ограниченном случае это число равно 1, но может быть больше, например, 10% от предела связи открытого db.

Любые идеи?

Спасибо.

P.S.

Я заметил this и this, но ни один из них не имеет отношения к мне.

ответ

10

Использование BlockingCollection<T>, которое реализует шаблон производителя/потребителя. Он потокобезопасен, поэтому вы можете получить доступ к нему из нескольких потоков одновременно. Ниже приведен пример того, как это будет использоваться:

var collection = new BlockingCollection<MyClass>(); 

// start a new background task to fill the queue 
Task.Factory.StartNew(() => { 
    while(thereIsStillStuffToStoreInTheDatabase) 
    { 
     var item = GetNextItem(); 
     collection.Add(item); 
    } 
    collection.CompleteAdding(); 
}); 

// GetConsumingEnumerable() blocks while empty until the producer 
// has more items or it signals that adding is complete 
foreach(var item in collection.GetConsumingEnumerable()) 
{ 
    // store item in database 
} 

Следует отметить, что выше реализация также может быть выполнена в обратном направлении, с фоном Task потребляющего из коллекции и основного рабочего потока, заполняющего его.

У Джозефа Альбахари отличная запись о задачах и параллелизме. Вы можете прочитать все об этом, и в частности о BlockingCollection, here.

+0

Только для ссылки на сайт Albahari вы заслуживаете +1. – mark

0

.net 4.0 предлагает несколько потокобезопасных структур данных.
ConcurrentQueue<T> должно быть то, что вы хотите.

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

+2

Нет, не выполняйте сигнализацию самостоятельно. Посмотрите на BlockingCollection в том же пространстве имен. –

Смежные вопросы