【问题标题】:Declare a variable per thread and manage them in c# Parallel.Foreach [closed]为每个线程声明一个变量并在 c# Parallel.Foreach 中管理它们 [关闭]
【发布时间】:2020-10-23 14:49:34
【问题描述】:

我正在编写一个代码来遍历一个庞大的对象列表,以便将它们保存在 DB 中。

我有一个计数器,每次迭代都会增加,当它达到 500 时,我将所有内容都保存在 DB 中(来自 StringBuilder)。

如果我按顺序进行,我没有问题,但需要很长时间。这就是为什么我想使用并行性来做到这一点。

我已经看到我无法为所有线程创建一个 StringBuilder,因此我需要为每个线程创建一个。

我的问题是: 如何为每个线程创建一个 StringBuilder? 然后,当静态计数器达到 500 个循环时,如何将所有 StringBuilder 对象持久化到 DB 并清空它们?

我有以下代码:

int counter = 0;

Parallel.ForEach(myList, element =>
{
    lock (balanceLock)
    {
        counter++;
    }

    var sb = new StringBuilder(); //I need one StringBuilder for thread, not for iteration
    
    ...
    
    if (decimal.Remainder(counter, 500) == 0)
        lock (balanceLock)
        {
            persistInDB(sb.toString());
            sb.Clear();
        }
});

【问题讨论】:

  • 如果你在里面使用锁,那么使用Parallel.ForEach 是没有意义的。该方法适用于数据并行 - 处理大量本地内存数据。不是通用并行执行,也绝对不是用于执行远程数据库调用
  • 你想做什么?您描述了您认为解决方案的样子,而不是实际问题。 huge list 将是例如 1M 内存对象。 100K会很多。 500 是极少量的数据。您可以使用单个 INSERT 命令插入所有这些行,或者使用 SqlBulkCopy 以使用最少的日志记录在单个批量操作中插入数据
  • 我想指出的是,在使用任务时,系统决定何时将工作交给另一个线程。
  • 如果您有一个大集合要发送到数据库,您可以使用FastMember's ObjectReader together with SqlBulkCopy 将数据插入数据库。
  • 关键是我在内存中的列表中最多可以有 10M 项,并且每个项都会在数据库上生成不同的查询。这就是并行处理的原因

标签: c# parallel.foreach


【解决方案1】:

最后我以顺序的方式解决了这个问题,将记录放在一个表中,并按照建议对数据库进行 SqlBulkCopy。

DataTable table = getDataTable();

myList.ForEach(element => {
    
    //...
    
    table.Rows.Add(getRow(element));

    if (decimal.Remainder(counter, 500) == 0){
        SqlConnection _db;
        _db.Open();
        
        using (SqlBulkCopy bulk = new SqlBulkCopy(_db)){
            var map1 = new SqlBulkCopyColumnMapping("columnName1", "columnName1");
            var map2 = new SqlBulkCopyColumnMapping("columnName2", "columnName2");
            //...
            
            bulk.ColumnMappings.Add(map1);
            bulk.ColumnMappings.Add(map2);
            //...
            
            bulk.DestinationTableName = "DestinationTableName";
            bulk.WriteToServer(table);

            bulk.Close();
        }
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-12-13
    • 1970-01-01
    • 1970-01-01
    • 2021-01-09
    • 2012-09-08
    • 2020-09-20
    • 1970-01-01
    • 2021-03-09
    相关资源
    最近更新 更多