为每个线程声明一个变量,并在c#Parallel.Foreach中对其进行管理

问题描述

我正在编写代码以遍历庞大的对象列表,以将其持久存储在数据库中。

每次迭代我都会增加一个计数器,当迭代次数达到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();
        }
});

解决方法

最后,我按照建议的顺序解决了这一问题,方法是将记录放在表中,并根据建议对数据库进行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();
        }
    }
}