我正在尝试利用.NET Framework4.0中的并行for循环。但是,我注意到,结果集中缺少了一些元素。
我有下面的代码片段。lhs.ListData是可空双的列表,rhs.ListData是可空的double的列表。
int recordCount = lhs.ListData.Count > rhs.ListData.Count ? rhs.ListData.Count : lhs.ListData.Count;
List<double?> listResult = new List<double?>(recordCount);
var rangePartitioner = Partitioner.Create(0, recordCount);
Parallel.ForEach(rangePartitioner, range =>
{
for (int index = range.Item1; index < range.Item2; index++)
{
double? result = lhs.ListData[index] * rhs.ListData[index];
listResult.Add(result);
}
});lhs.ListData的长度为7964,rhs.ListData的长度为7962。当我执行"*“操作时,listResult只有7867作为输出。两个输入列表中都有空元素。
我不知道执行过程中发生了什么。有什么理由让我在结果集中看到更少的元素?请指点..。
发布于 2012-10-09 02:42:42
正确的方法是使用LINQ的IEnumerable.AsParallel()扩展。它为您完成了所有的分区,而PLINQ中的所有内容都是线程安全的。还有一个名为Zip的LINQ扩展,它根据给定的函数将两个集合压缩为一个集合。然而,这并不是您所需要的,因为它只是两个列表中的较短的长度,而不是更长的列表。这样做可能比较容易,但首先将两个列表中较短的列表扩展为较长的列表,在列表的末尾填充null。
IEnumerable<double?> lhs, rhs; // Assume these are filled with your numbers.
double?[] result = System.Linq.Enumerable.Zip(lhs, rhs, (a, b) => a * b).AsParallel().ToArray();以下是Zip上的MSDN页面
http://msdn.microsoft.com/en-us/library/dd267698%28VS.100%29.aspx
发布于 2012-10-09 02:20:45
这可能是因为List<T>上的操作(例如Add)并不是线程安全的--您的结果可能会有所不同。作为解决办法,您可以使用锁,但这将大大降低性能。
看起来,您只希望结果列表中的每一项都是两个输入列表中相应索引项的乘积,不如使用PLINQ:
var listResult = lhs.AsParallel()
.Zip(rhs.AsParallel(), (a,b) => a*b)
.ToList();不知道为什么在这里选择并行,如果这是必要的话,我会进行测试--这真的是应用程序中的瓶颈吗?
发布于 2012-10-09 02:33:51
您正在使用List<double?>存储结果,但是Add方法并不是线程安全的。您可以使用显式索引来存储结果(而不是调用Add):
listResult[index] = result;https://stackoverflow.com/questions/12791925
复制相似问题