Делая несколько предположений, я еще не получил ответ на комментарий к вашему вопросу.
Я предполагаю, что здесь происходит большое количество рабочих потоков, поскольку действия (действие, являющееся единицей работы, выполняемой на параллельном foreach) занимают больше времени, чем указанное время, поэтому базовый ThreadPool увеличивает количество потоков. Это произойдет, когда ThreadPool будет следовать алгоритму увеличения пула, чтобы новые задачи не блокировались существующими долгосрочными задачами, например, если все мои текущие потоки были заняты в течение полсекунды, я начну добавлять больше потоков в пул. Однако вы столкнетесь с проблемами, если все задачи будут выполняться долго, а добавленные вами новые задачи сделают существующие задачи еще дольше. Вот почему вы, вероятно, видите большое количество рабочих потоков - возможно, из-за перегрузки диска или медленного сетевого ввода-вывода (если задействованы сетевые диски).
Я также предполагаю, что файлы копируются с одного диска на другой, или они копируются из одного места в другое на том же диске. В этом случае добавление темы к проблеме не очень поможет. На исходном и целевом дисках есть только один набор головок, поэтому попытка заставить их делать несколько вещей одновременно может привести к замедлению:
- Головки дисков будут качаться повсюду.
- Кэши вашего диска \ ОС могут часто аннулироваться.
Это может не быть большой проблемой для распараллеливания.
Обновление
В ответ на ваш комментарий, если вы получаете ускорение, используя несколько потоков в меньших наборах данных, вы можете поэкспериментировать с уменьшением максимального количества потоков, используемых в вашем параллельном foreach, например,
ParallelOptions options = new ParallelOptions { MaxDegreeOfParallelism = 2 };
Parallel.ForEach(Directory.GetFiles(Src), options, file =>
{
//Do stuff
});
Но, пожалуйста, имейте в виду, что смещение диска может свести на нет любые преимущества распараллеливания в общем случае. Поиграйте с ним и оцените свои результаты.