就线程安全问题而言,可以做或者我需要使用不同的集合吗?
List<FileMemberEntity> fileInfo = getList();
Parallel.ForEach(fileInfo, fileMember =>
{
//Modify each fileMember
}
答案 0 :(得分:28)
只要您只修改传递给方法的项目的内容,就不需要锁定。
(当然,前提是列表中没有重复引用,即对同一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
});
答案 1 :(得分:5)
因为你刚读书,所以你很安全。只是在迭代其项目时不要修改列表。
答案 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
答案 3 :(得分:1)
如果FileMemberEntity
个对象的作用顺序无关紧要,可以使用List<T>
,因为您没有修改列表。
如果必须确保某种排序,可以使用OrderablePartitioner<T>
作为基类并实现适当的分区方案。例如,如果FileMemberEntity
具有某种分类,并且您必须按某种特定顺序处理每个类别,那么您可能希望采用此路线。
假设你有
对象1类别A
对象2类别A
对象3类别B
在使用Object 2 Category A
迭代Object 3 Category B
时,无法保证在处理List<T>
之前处理Parallel.ForEach
。
您链接到的MSDN文档提供了如何执行此操作的示例。