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