0

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

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

当我尝试使用Parallel.forthen 迭代集合时,它只是挂断并且花费了太长时间。

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

4

2 回答 2

0

如果您已经在内存中拥有该对象,并且必须将它们转换为 DataTable,那么您就大错特错了。DataTable 不是线程安全的

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

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

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

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

于 2015-05-01T08:47:09.957 回答
0

虽然DataTable 操作(包括 .NewRow() )不是线程安全的,但您的工作仍然可以 使用并行循环中的线程局部变量并行化

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;
    }

但是,只有在转换“您的对象实例”-> DataRow所节省的时间 大于在执行结束时加入结果所损失的时间(锁 + DataTable 合并)时,并行执行才会有益。仅当您的转换有点占用大量 CPU 时才有可能。在我的示例中,转换 (dr[0] = source[i]) 根本不会占用大量 CPU,因此更可取的是顺序执行。

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

于 2015-05-01T12:58:32.770 回答