Parallel.ForEach on List <Object> Безопасность потоков
Насколько Thread Safety идет, это нормально делать или мне нужно использовать другую коллекцию?
List<FileMemberEntity> fileInfo = getList();
Parallel.ForEach(fileInfo, fileMember =>
{
//Modify each fileMember
}
Ответы
Ответ 1
Пока вы только изменяете содержимое элемента, переданного методу, блокировки не требуется.
(Разумеется, в списке нет дублирующихся ссылок, т.е. двух ссылок на один и тот же экземпляр FileMemberEntity
.)
Если вам нужно изменить сам список, создайте копию, которую вы можете выполнить, и используйте блокировку при изменении списка:
List<FileMemberEntity> fileInfo = getList();
List<FileMemberEntity> copy = new List<FileMemberEntity>(fileInfo);
object sync = new Object();
Parallel.ForEach(copy, fileMember => {
// do something
lock (sync) {
// here you can add or remove items from the fileInfo list
}
// do something
});
Ответ 2
Ты в безопасности, так как ты просто читаешь. Просто не изменяйте этот список, пока вы выполняете итерацию по его элементам.
Ответ 3
Мы должны использовать меньше объекта блокировки, чтобы сделать его быстрее. Только заблокировать объект в разных локальных потоках Parrallel.ForEach:
List<FileMemberEntity> copy = new List<FileMemberEntity>(fileInfo);
object sync = new Object();
Parallel.ForEach<FileMemberEntity, List<FileMemberEntity>>(
copy,
() => { return new List<FileMemberEntity>(); },
(itemInCopy, state, localList) =>
{
// here you can add or remove items from the fileInfo list
localList.Add(itemInCopy);
return localList;
},
(finalResult) => { lock (sync) copy.AddRange(finalResult); }
);
// do something
Ссылка: http://msdn.microsoft.com/en-gb/library/ff963547.aspx
Ответ 4
Если неважно, в каком порядке действуют объекты FileMemberEntity
, вы можете использовать List<T>
, потому что вы не изменяете список.
Если вы должны обеспечить какой-то порядок, вы можете использовать OrderablePartitioner<T>
как базовый класс и реализовать соответствующую схему секционирования. Например, если FileMemberEntity
имеет какую-то категоризацию, и вы должны обрабатывать каждую из категорий в определенном порядке, вы хотите пойти по этому маршруту.
Гипотетически, если у вас
Объект 1 Категория A
Объект 2 Категория A
Объект 3 Категория B
нет гарантии, что Object 2 Category A
будет обработан до того, как Object 3 Category B
будет обработан при повторении a List<T>
с помощью Parallel.ForEach
.
Документация MSDN, на которую вы ссылаетесь, дает пример того, как это сделать.