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



我正在编写一段代码,用于遍历一个庞大的对象列表,以便将它们持久化到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();
}
});

最后,我按照建议,将记录放在一个表中,并对数据库创建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();
}
}
}

最新更新