2013-07-31 3 views
1

Я использую шаблон производителя/потребителя с поддержкой BlockingCollection, чтобы читать данные с файла, анализировать/преобразовывать, а затем вставлять в базу данных. Код, который у меня есть, очень похож на то, что можно найти здесь: http://dhruba.name/2012/10/09/concurrent-producer-consumer-pattern-using-csharp-4-0-blockingcollection-tasks/Как использовать многие потребительские потоки с помощью BlockingCollection

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

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

В качестве альтернативы, как бы вы выбрали количество потребительских потоков? 2 не кажется правильным для меня, но я не уверен, что будет лучшим #. Мысли о лучшем способе выбора количества потребительских потоков?

+0

Нитки не являются волшебным решением для каждой проблемы с перфорацией. Добавление большего количества стремится либо создавать только более ожидающие потоки, либо раздраженный администратор базы данных, который не любит, чтобы ваше приложение полностью зависало на сервере. –

+0

Это приложение будет работать во время запланированного простоя, поэтому удача БД приемлема. Я просто хочу свести к минимуму время, когда оно падает. – Porco

+0

Это связано с тем, что время простоя в полночь, и вы просто не хотите придерживаться этого долго, чтобы попробовать? –

ответ

3

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

Я решил проблему блокировки вывода (блокирование потребителей при попытке обновления базы данных), добавив еще один BlockingCollection, что потребители вставляют свои завершенные пакеты. Отдельный поток читает эту очередь и обновляет базу данных. Так что это выглядит примерно так:

input thread(s) => input queue => consumer(s) => output queue => output thread 

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

Я показываю очень простой пример этого (с использованием одного потребителя) в своей статье Simple Multithreading, Part 2. Это работает с фильтром текстовых файлов, но понятия одинаковы.

+0

Это потрясающе! пакетное обновление БД звучит точно так, как мне нужно. – Porco

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