就线程安全而言,这可以做或我需要使用不同的集合吗?Parallel.ForEach上市<Object>线程安全
List<FileMemberEntity> fileInfo = getList();
Parallel.ForEach(fileInfo, fileMember =>
{
//Modify each fileMember
}
就线程安全而言,这可以做或我需要使用不同的集合吗?Parallel.ForEach上市<Object>线程安全
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
});
正在收集的内容....收集中包含的内容是否正确? –
@MicahArmantrout:作为'fileMember'传递给方法的'FileMemberEntity'实例中的内容。 – Guffa
那么这将使所有其他线程停止,直到它离开锁或与Parallel.ForEach将线程继续到列表中的另一个项目? –
你很安全,因为你只是在阅读。在迭代其项目时,不要修改列表。
我正在修改集合中的项目 –
这很好,只要因为你没有修改实际的集合本身。您无法对其中的项目重新排序,也无法向其添加或删除项目。 – Henrik
因此,如果我正在更新列表中的项目,只要最后我不更改实际的集合,这并不重要? –
如果FileMemberEntity
对象执行的操作顺序无关紧要,则可以使用List<T>
,因为您没有修改该列表。
如果您必须确保某种排序,则可以使用OrderablePartitioner<T>
作为基类并实施适当的分区方案。例如,如果FileMemberEntity
有某种分类,并且您必须按某种特定顺序处理每个类别,则您需要转到该路线。
可以想像,如果你有
对象1 A类
对象2 A类
对象3 B类
没有保证Object 2 Category A
将前被处理使用迭代List<T>
时处理。
您链接到的MSDN文档提供了一个如何执行此操作的示例。
我在修改foreach中的集合 –
如果您要修改集合中的对象(而不是集合本身),那就好了。 –
非常感谢! –
我们应该使用更少的锁对象来使其更快。只有在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
请保持问题奇异。 – 2012-06-27 17:53:04
你在修改foreach循环中的任何内容吗?如果不是,那么可能不需要考虑线程安全性。如果您正在修改,那么您需要执行锁定 – Didaxis
我可以使用不同的集合并且不需要锁定 –