Я бы рекомендовал использовать Thread Pool для одновременного выполнения нескольких задач из вашей очереди управляемыми пакетами, используя список активных задач, который выводится из очереди задач.
В этом сценарии ваш основной рабочий поток первоначально вставит N задач из очереди в список активных задач, которые будут отправлены в пул потоков (скорее всего, с использованием QueueUserWorkItem ), где N представляет управляемую сумму, которая не перегружает пул потоков, не загружает ваше приложение расходами на планирование потоков и синхронизацию, или не высасывает доступную память из-за комбинированных накладных расходов ввода-вывода каждой задачи.
Всякий раз, когда задача сообщает о завершении рабочему потоку, вы можете удалить ее из списка активных задач и добавить следующую из очереди задач для выполнения.
Это позволит вам иметь непрерывный набор из N задач из вашей очереди. Вы можете манипулировать N, чтобы повлиять на характеристики производительности и найти то, что лучше в ваших конкретных условиях.
Поскольку в конечном итоге вы оказались в узком месте из-за аппаратных операций (дисковый ввод-вывод и сетевой ввод-вывод, процессор), я думаю, чем меньше, тем лучше. Две задачи пула потоков, работающие с дисковым вводом-выводом, скорее всего, не будут выполняться быстрее, чем одна.
Вы также можете реализовать гибкость в размере и содержании списка активных задач, ограничив его заданным количеством задач определенного типа. Например, если вы работаете на машине с 4 ядрами, вы можете обнаружить, что самая эффективная конфигурация - это четыре задачи с привязкой к процессору, выполняющиеся одновременно, с одной задачей с привязкой к диску и сетевой задачей.
Если у вас уже есть одна задача, классифицированная как задача дискового ввода-вывода, вы можете подождать, пока она не будет завершена, прежде чем добавлять другую задачу дискового ввода-вывода, и вы можете запланировать выполнение задачи, связанной с ЦП или сетью, в то же время .
Надеюсь, это имеет смысл!
PS: Есть ли у вас зависимости от порядка задач?