我不在.NET 4上。
我从数据源中获取了一个巨大的列表。当列表中的元素数高于X时,我想分区列表,将每个分区分配给一个线程。处理分区后,我想合并它们。
var subsets = list.PartitionEager(50000);
//var subsets = list.Partition<T>(50000);
Thread[] threads = new Thread[subsets.Count()];
int i = 0;
foreach (var set in subsets)
{
threads[i] = new Thread(() => Convertor<T>(set));
threads[i].Start();
i++;
}
for (int j = 0; j < i; j++)
{
threads[j].Join();
}
转换器方法是一种静态方法,它采用列表并进行一些查找。
public static void Convertor<T>(List<T> list) where T : IInterface {
foreach (var element in list)
{
**// do some lookup and assing a value to element
// then do more lookup and assign a value to element**
}
}
当我运行此代码时,即使我知道大多数元素都将被赋值。事实上他们回来了。
我知道列表的副本将传递给方法,但对元素的任何更改都应该反映在upper方法中。然而,这只发生在最后一个子集中。
我甚至添加了一些代码将列表合并为一个。
list.Clear();
foreach (var set in subsets)
{
list.AddRange(set);
}
分区代码:
public static List<List<T>> PartitionEager<T>(this List<T> source, Int32 size)
{
List<List<T>> merged = new List<List<T>>();
for (int i = 0; i < Math.Ceiling(source.Count / (Double)size); i++)
{
merged.Add(new List<T>(source.Skip(size * i).Take(size)));
}
return merged;
}
我做错了什么?如何解决这个问题?我想在查找后分配值的元素?这与同步或参数传递有关吗?
答案 0 :(得分:3)
如果选择.NET 4,则可以使用Parallel.For或Parallel.ForEach。这些方法为您自动处理分区,并在不同系统上跨多个并发度的可伸缩性方面提供许多其他优势。
答案 1 :(得分:2)
在创建线程时看起来你有modified closure
。如果我是正确的,那么所有线程都会更新相同的(最后一个)集。以这种方式修改代码:
foreach (var set in subsets)
{
var setLocalCopy = set;
threads[i] = new Thread(() => Convertor<T>(setLocalCopy));
threads[i].Start();
i++;
}