Интернет заполнен рекомендациями: "если у вас много небольших независимых задач, которые можно / нужно запускать параллельно" используйте ThreadPool — он умница и сам справится.
Видимо я что-то сильно недопонимаю, но когда задач действительно много (сотни и больше) то ни разу не умница, и не справляется. Вешает машину, задачи вылетают по таймауту...
Пытался выставлять ограничение в ThreadPool.SetMaxThreads — в целом ситуация не решилась.
В результате загружаю в ThreadPool задачи контролируя сколько у него занято потоков, чтобы было не более Environment.ProcessorCount
Не покидает ощущение, что все-таки что-то не так делаю.
Здравствуйте, CyberRussia, Вы писали:
CR>Интернет заполнен рекомендациями: "если у вас много небольших независимых задач, которые можно / нужно запускать параллельно" используйте ThreadPool — он умница и сам справится.
CR>Видимо я что-то сильно недопонимаю, но когда задач действительно много (сотни и больше) то ни разу не умница, и не справляется. Вешает машину, задачи вылетают по таймауту... CR>Пытался выставлять ограничение в ThreadPool.SetMaxThreads — в целом ситуация не решилась. CR>В результате загружаю в ThreadPool задачи контролируя сколько у него занято потоков, чтобы было не более Environment.ProcessorCount
CR>Не покидает ощущение, что все-таки что-то не так делаю.
А зачем ThreadPool? TPL сейчас все используют. Что за операции, кстати?
Здравствуйте, CyberRussia, Вы писали:
CR>Двух типов CR>- загрузка данных из внешнего источника и сохранение в БД. CR>- обработка данных из БД и сохранение в БД
ThreadPool не особо подойдет для I/O. TPL и TaskCreationOptions.LongRunning. Ну или вообще архитектуру перелопатить.
F>ThreadPool не особо подойдет для I/O. TPL и TaskCreationOptions.LongRunning. Ну или вообще архитектуру перелопатить.
Хм, а для чего тогда ThreadPool подойдет?
F>TPL используют.
Окей, значит, если я в цикле запущу Task.Run(() => от нескольких сотен, до нескольких десятков тысяч раз, все будет замечательно — машина не затупит, по таймауту не повалится?
Здравствуйте, CyberRussia, Вы писали:
CR>Окей, значит, если я в цикле запущу Task.Run(() => от нескольких сотен, до нескольких десятков тысяч раз, все будет замечательно — машина не затупит, по таймауту не повалится?
Parallel.For
Здравствуйте, CyberRussia, Вы писали:
CR>Интернет заполнен рекомендациями: "если у вас много небольших независимых задач, которые можно / нужно запускать параллельно" используйте ThreadPool — он умница и сам справится.
он умница, но только когда используется в условиях для которых он задуман.
например разные части системы у тебя пуляют много коротких CPU задачек.
без пула, ты будеш вынужден сам создавать поток под задачу и потом дестроить его.
если задачки короткие, то накладные расходы на создание потоков будут уже заметны, поэтому пул поток тут полезен.
но чудес не бывает, реально одновременно может выполняться задачек столько сколько ядер.
поэтому когда задач слишком много, то в какой-то момент узким местом станет кол-во ядер и новые задачи просто будут ждать своей очереди.
если в задачах у тебя в основном IO, то тебе надо на асинхронщину переходить.
Здравствуйте, Farsight, Вы писали:
F>Здравствуйте, CyberRussia, Вы писали:
CR>>Окей, значит, если я в цикле запущу Task.Run(() => от нескольких сотен, до нескольких десятков тысяч раз, все будет замечательно — машина не затупит, по таймауту не повалится? F>Parallel.For
Здравствуйте, Farsight, Вы писали:
F>А зачем ThreadPool? TPL сейчас все используют. Что за операции, кстати?
Таски из TPL по умолчанию используют тредпульные потоки. Таска — всего лишь удобная абстракция, но рулить потоками всё равно как-то приходится.
The default scheduler for the Task Parallel Library and PLINQ uses the .NET Framework thread pool, which is represented by the ThreadPool class, to queue and execute work. The thread pool uses the information that is provided by the Task type to efficiently support the fine-grained parallelism (short-lived units of work) that parallel tasks and queries often represent.
Здравствуйте, Философ, Вы писали:
Ф>Таски из TPL по умолчанию используют тредпульные потоки. Таска — всего лишь удобная абстракция, но рулить потоками всё равно как-то приходится.
Имелось в виду "зачем threadpool использовать напрямую, когда есть удобные абстракции из TPL".
Здравствуйте, Farsight, Вы писали:
F>Здравствуйте, Философ, Вы писали:
Ф>>Таски из TPL по умолчанию используют тредпульные потоки. Таска — всего лишь удобная абстракция, но рулить потоками всё равно как-то приходится. F>Имелось в виду "зачем threadpool использовать напрямую, когда есть удобные абстракции из TPL".
Иногда сами таски не нужны. Таски — объекты, котороые можно ждать, анализовать состояние, компоновать и т.д.
Часто бывает, что вполне достаточно запульнуть задачу, и на этом всё — такая дополнительная абстракция просто не нужна.
Всё сказанное выше — личное мнение, если не указано обратное.
D>Таку человека активное использование IO операций, все-таки дучше на асинках.
Как я понимаю асинк операции хороши, когда после чего-то длительного еще код имеется. А у меня самостоятельный блок из кучи независимых параллельных кусков, по сути являющихся одним методом, но с разным входным параметром. И после ничего, то есть грубо говоря, загрузили кучу данных и все. Соответственно каждый кусок (вызов метода) я кидаю в ThreadPool и больше ничего.
Ну, если быть совсем точным есть часть после, но он должен выполниться только когда совсем все параллельные куски полностью отработали.
Здравствуйте, Философ, Вы писали:
Ф>Иногда сами таски не нужны. Таски — объекты, котороые можно ждать, анализовать состояние, компоновать и т.д. Ф>Часто бывает, что вполне достаточно запульнуть задачу, и на этом всё — такая дополнительная абстракция просто не нужна.