列出分而治之 - 按价值或参考传递

时间:2011-03-23 22:11:34

标签: c# multithreading list reference parameter-passing

我不在.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;
    }

我做错了什么?如何解决这个问题?我想在查找后分配值的元素?这与同步或参数传递有关吗?

2 个答案:

答案 0 :(得分:3)

如果选择.NET 4,则可以使用Parallel.ForParallel.ForEach。这些方法为您自动处理分区,并在不同系统上跨多个并发度的可伸缩性方面提供许多其他优势。

答案 1 :(得分:2)

在创建线程时看起来你有modified closure。如果我是正确的,那么所有线程都会更新相同的(最后一个)集。以这种方式修改代码:

        foreach (var set in subsets)
        {
            var setLocalCopy = set;
            threads[i] = new Thread(() => Convertor<T>(setLocalCopy));
            threads[i].Start();
            i++;
        }