#c_sharp #многопоточность #циклы #foreach #parallel
У меня есть список. Необходимо прогнать все его элементы, вызвать в каждой итерации функцию расчета и при каком-то условии, удалить элемент из цикла и продолжить итерации. Вначале думал про for и если удаляем, делать i--, т.к. уменьшилось количество элементов на 1, но это не сделать при параллельном прогоне, поэтому думаю сделать подобное в foreach, чтобы не привязываться к индексу элемента. Но при изменение foreach выскакивает исключение, что логично. Можно ли как-нибудь прогнать параллельно по циклу и по условию, если что удалить элемент. Чтобы это не сказывалась на других элементах в параллельных потоках?
Ответы
Ответ 1
Если удалять элемент из коллекции сразу же на месте не требуется — заведите еще одну (потокобезопасную) коллекцию, элементы подлежащие удалению складывайте в нее, после завершения первого цикла просто удалите из первой коллекции все элементы, присутствующие во второй: // заводим коллекцию var forRemoving = new ConcurrentBag- (); foreach (var item in items) { ... // складываем в нее элементы подлежащие удалению forRemoving.Add(item); } // удаляем foreach (var item in forRemoving) items.Remove(item); Если для вашей задачи не принципиально удаление элементов из входной коллекции, а подойдет также вариант с формированием новой коллекцией — можно воспользоваться функционалом Parallel Linq: var result = items.AsParallel() .Where(item => condition(item)) .ToList();
Ответ 2
У меня есть список. Если список - это именно List, то используй обычный цикл for. Обращаю внимание, что удаление нескольких элементов через Remove неэффективно, поскольку приведёт к квадратичной асимптотике (хвост всё время сдвигается). Правильным вариантом было бы использовать метод RemoveAll. Ну либо написать обраотку списка в один проход с ручным сдвигом конца по мере порверки.
Комментариев нет:
Отправить комментарий