在循环中迭代大量数据并准备数据表的最佳方法是什么

时间:2015-05-01 08:45:24

标签: c# for-loop foreach iteration parallel.for

我有需要转换为数据表的对象列表。

收集长度存在20K或更多。

当我尝试使用Parallel.for迭代集合时,它只是挂断并花费更长的时间。

任何人都可以建议将对象列表最佳转换为数据表的最佳方法吗?

2 个答案:

答案 0 :(得分:0)

如果你已经有了内存中的对象而必须将它们转换为DataTable,那你就搞砸了。 DataTable不是线程安全的

https://social.msdn.microsoft.com/Forums/en-US/ddcdac9d-35e7-4b9f-a367-242bf60c42f2/faq-item-is-datatable-thread-safe

而且你的内存使用量增加了一倍。

我唯一的建议是,您可以将现有集合包装在继承自DataTable的对象中,并覆盖或隐藏方法,以便它们引用您的基础列表。

但是我认为这不太可能是解决问题的“好”或简单方法。最好的方法是不再需要DataTable

答案 1 :(得分:0)

虽然 DataTable操作(包括.NewRow())不是线程安全的,但您的工作仍然可以并行化 using thread-local variables in the parallel loop

List<string> source = Enumerable.Range(0, 20000).Select(i => i.ToString()).ToList();
DataTable endResult = CreateEmptyTable();
object lck = new object();

Parallel.For(
    0, source.Count,
    () => CreateEmptyTable(), // method to initialize the thread-local table
    (i, state, threadLocalTable) => // method invoked by the loop on each iteration
    {
        DataRow dr = threadLocalTable.NewRow();

        // running in parallel can only be beneficial 
        // if you do some CPU-heavy conversion in here
        // rather than simple assignment as below
        dr[0] = source[i];

        threadLocalTable.Rows.Add(dr);
        return threadLocalTable;
    },

    // Method to be executed when each partition has completed. 
    localTable =>
    {
        // lock to ensure that the result table 
        // is not screwed by merging from multiple threads simultaneously
        lock (lck)
        {
            endResult.Merge(localTable);
        }
    }
);

,其中

    private static DataTable CreateEmptyTable()
    {
        DataTable dt = new DataTable();
        dt.Columns.Add("MyString");
        return dt;
    }

然而如果转化时节省的时间 &#39;您的对象实例&#39;那么并行执行只会有用。 - &GT; DataRow 大于在执行结束时加入结果时丢失的时间

PS。以上修改为顺序的示例在我的IntelCore-i7-3537U上完成了20ms。如果您的顺序执行时间很短,您可能根本不想打扰并行执行。