Thread / threadpool или фоновый работник

Я хотел бы знать, что использовать для задач, требующих высокой производительности. Backgroundworker, Thread или ThreadPool?

До сих пор я работал с Threads, но мне нужно улучшить скорость моих приложений.


person user2468035    schedule 09.06.2013    source источник
comment
Это зависит от того, как их использовать, а не от того, что использовать.   -  person I4V    schedule 09.06.2013


Ответы (3)


BackgroundWorker - это то же самое, что и поток пула потоков. Он добавляет возможность запускать события в потоке пользовательского интерфейса. Очень полезно для отображения прогресса и для обновления пользовательского интерфейса с результатами. Таким образом, его типичное использование - предотвратить зависание пользовательского интерфейса, когда необходимо выполнить работу. Производительность - не первая цель, в отличие от асинхронного выполнения кода. Этот шаблон также умело расширен в более поздних версиях .NET классом Task ‹> и ключевыми словами async / await.

Потоки пула потоков полезны, чтобы избежать потребления ресурсов. Поток - это дорогостоящий объект операционной системы, и вы можете создать очень ограниченное их количество. Поток занимает 5 дескрипторов операционной системы и мегабайт адресного пространства виртуальной памяти. Нет метода Dispose () для раннего освобождения этих дескрипторов. Пул потоков существует в первую очередь для повторного использования потоков и для обеспечения того, чтобы не слишком много из них было активным. Важно, чтобы вы использовали поток пула потоков только тогда, когда выполняемая им работа ограничена, в идеале - не более полсекунды. И не часто блокирует. Поэтому он лучше всего подходит для коротких периодов работы, а не для всего, что имеет значение. Обработка завершения ввода-вывода - идеальная задача для потока TP.

Да, можно также использовать потоки для повышения производительности программы. Это можно сделать с помощью Thread или Task ‹>, использующего TaskContinuationOptions.LongRunning. Есть несколько жестких требований для улучшения производительности, они довольно жесткие:

  • Вам нужно больше, чем один поток. В идеальном случае два потока могут вдвое сократить время, необходимое для выполнения работы. И чем меньше, тем больше потоков вы используете. Однако приблизиться к этому идеалу сложно, его нельзя бесконечно масштабировать. Google "закон Амдала" для информации.
  • Вам нужна машина с многоядерным процессором. В наши дни легко получить. Количество создаваемых вами потоков не должно превышать количество доступных ядер. Использование большего количества обычно снижает производительность.
  • Вам нужно задание, связанное с вычислением, при котором механизм выполнения процессора должен быть ограниченным ресурсом. Это довольно распространенное явление, но, конечно же, не слэмданк. Многие задания фактически ограничены пропускной способностью ввода-вывода, например, чтение из файла или запрос базы данных. Или ограничены скоростью, с которой процессор может читать данные из ОЗУ. Такие задания не выигрывают от потоков, у вас будет несколько доступных механизмов выполнения, но у вас по-прежнему будет только один диск и одна шина памяти.
  • Вам нужен алгоритм, который может распределять работу по нескольким потокам без необходимости синхронизации. Обычно эту проблему сложно решить, многие алгоритмы очень последовательны по своей природе и их нелегко распараллелить.
  • Вам потребуется время и терпение, чтобы код был стабильным и хорошо работающим. Написание многопоточного кода сложно, и гонка потоков, которая приводит к сбою вашей программы один раз в месяц или иногда дает неверный результат, может отнимать у вас много времени.
person Hans Passant    schedule 09.06.2013
comment
отличный ответ! Я думаю, что получил то, что мне нужно. как мне закрыть этот вопрос? (Я новичок в этом). - person user2468035; 09.06.2013
comment
@user - просто отметьте ответ. Щелкните галочку слева от сообщения, в котором был дан ответ на ваш вопрос. - person Hans Passant; 09.06.2013
comment
Вы говорите не использовать BackgroundWorker для длительных задач (вместо этого используйте Thread или Task). Это потому, что он медленнее по сравнению с потоком / задачей, или это связано с памятью, или потому, что он тормозит систему, или это какая-то другая проблема? Предположим, у вас неприятно параллельная проблема с примерно 4-20 ядрами / потоками (с соответствующими физическими ядрами), и решение проблемы может занять несколько минут. - person Dan W; 09.05.2016
comment
Вы уже знаете это из своего последнего вопроса, нет смысла задавать его снова. - person Hans Passant; 09.05.2016
comment
Как вы могли вообще утверждать, что в идеальном случае вы можете половину времени, необходимого для выполнения работы, используя два потока. - person omerfarukdogan; 19.05.2016
comment
Понятия не имею, как я не мог, даже в телефонах сегодня многоядерные процессоры. - person Hans Passant; 19.05.2016

Структура для запуска задач, интенсивно использующих ЦП, в потоках не имеет отношения к вашей проблеме, если только у вас нет слишком мелких подзадач.

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

person Will    schedule 09.06.2013
comment
спасибо, это действительно увеличило скорость. теперь он выполняет несколько задач одновременно, что улучшило мою производительность. еще раз спасибо - person user2468035; 09.06.2013

Этот выбор не имеет особого значения. BackgroundWorker - это поток ThreadPool, так что в любом случае никакой разницы. Однако вы можете попытаться оптимизировать количество потоков с помощью ThreadPool.SetMaxThreads.

И вы можете использовать класс System.Threading.Task, который может помочь оптимизировать параллельное выполнение.

person JeffRSon    schedule 09.06.2013