我的代码确实很简单的东西
名单已有的元素。 我有大约25000元(我希望能有更多的)列表中的每个元素小(日期时间)。
List<DateTime> newList = new List<DateTime>();
Parallel.ForEach(list, l => newlist.Add(new DateTime(l.Ticks + 5000)));
即,根据每个元素上,我创造新的元素,并将它们添加到不同的列表。 但是,这似乎并没有成为一个良好的编程方法。 我打这个例外有时 ,但不是每次。
IndexOutOfRangeException : {"Index was outside the bounds of the array."}
我们可以添加使用Parallel.ForEach()元素的列表? 如果是的话,为什么我打这个错误吗? 如果没有,为什么?
你会怎样真的想在这种情况下更是这样的:
newlist = list.AsParallel().Select(l => new DateTime(l.Ticks + 5000)).ToList();
虽然你应该测量的性能,看看这种情况下,即使从并行化的好处。
尝试使用,增加了所有的线程局部变量的newList作为这样的最终结果线程局部变量...
Parallel.ForEach(list, () => DateTime.MinValue, (l, state, date) =>
{
date = new DateTime(l.Ticks+5000);
return date;
},
finalresult =>
{
lock (newList)
{
newList.Add(finalresult);
}
});
第一个参数是你的旧列表中的第二个参数是(我只是初始化为datetime分钟)每个线程的初始值。 第三PARAM块是如下 - 的l是相同的代码; 状态是Paralleloption对象,你可以退出并行循环的,如果你选择; 最后是可变的立场表示线程局部变量。 该finalresult PARAM表示每个线程局部变量的最终结果,并呼吁每个线程 - 它的存在,你可以把newList的锁,并添加到newList共享变量。 在理论上,这工作。 我在自己的代码中使用类似的编码。 希望这可以帮助你或其他人。
因为每个人都有提及,似乎有这样做的并行任何情况下。 这肯定会远远慢。 然而,对于完成,这有时会失败的原因是有多数民众赞成由多个线程写入列表对象上没有锁。 补充一点:
object _locker = new object();
List<DateTime> newList = new List<DateTime>();
Parallel.ForEach(list, l => lock (_locker) newlist.Add(new DateTime(l.Ticks + 5000)));
目前根本没有足够的工作该做的使用,以保证Parallel.ForEach
也是List<T>
不是线程安全的,所以你就必须锁定,如果你想添加并行同一列表。 只需使用普通的循环。
这将有效地调用List<T>.Add
同时,还根据MSDN文档List<T>
“任何实例成员不能保证线程安全的。”
即使是(线程安全的),这是太便宜的,从并行执行(而不是并行执行的开销)中受益。 你有没有实际测量你的表现? 25000元是不是很多。
你真的需要这些在一个列表? 如果你需要的是枚举在foreach列表中,你应该这样做,而不是,因为它会用少得多的内存:
IEnumerable<DateTime> newSequence = list.Select(d => new DateTime(d.Ticks + 5000));
如果你真的需要这些列表中,只是在末尾添加.ToList():
var newSequence = list.Select(d => new DateTime(d.Ticks + 5000)).ToList();
这几乎可以肯定将是速度不够快,你并不需要并行化。 事实上,这可能是比做得并行,因为这将有更好的内存性能更快。