是否可以在我的代码中提取代码部分并让它在多个线程中运行?
该应用程序通过网络将数据从FoxPro数据库复制到我们的SQL服务器(文件非常庞大,因此批量复制需要以增量方式进行...
它有效,但我想提高速度。
1)通过让我标记的部分以多个线程运行,或者作为替代,
2)不循环遍历数据行中的每一列,
我选择了第二个选项...(更新后面的代码)
CODE
private void BulkCopy(OleDbDataReader reader, string tableName, Table table)
{
if (Convert.ToBoolean(ConfigurationManager.AppSettings["CopyData"]))
{
Console.WriteLine(tableName + " BulkCopy Started.");
try
{
DataTable tbl = new DataTable();
foreach (Column col in table.Columns)
{
tbl.Columns.Add(col.Name, ConvertDataTypeToType(col.DataType));
}
int batch = 1;
int counter = 0;
DataRow tblRow = tbl.NewRow();
while (reader.Read())
{
counter++;
////This section changed
object[] obj = tblRow.ItemArray;
reader.GetValues(obj);
tblRow.ItemArray = obj;
////**********
tbl.LoadDataRow(tblRow.ItemArray, true);
if (counter == BulkInsertIncrement)
{
Console.WriteLine(tableName + " :: Batch >> " + batch);
counter = PerformInsert(tableName, tbl, batch);
batch++;
}
}
if (counter > 0)
{
Console.WriteLine(tableName + " :: Batch >> " + batch);
PerformInsert(tableName, tbl, counter);
}
tbl = null;
Console.WriteLine("BulkCopy Success!");
}
catch (Exception)
{
Console.WriteLine("BulkCopy Fail!");
}
finally
{
reader.Close();
reader.Dispose();
}
Console.WriteLine(tableName + " BulkCopy Ended.");
}
}
更新 我去了第二个选项
我不知道在while(reader.Read())循环内部,我可以执行以下操作。我没有帮助大大提高应用程序性能
while (reader.Read())
{
object[] obj = tblRow.ItemArray;
reader.GetValues(obj);
tblRow.ItemArray = obj;
tbl.LoadDataRow(tblRow.ItemArray, true);
}
答案 0 :(得分:4)
如果你把初学者的错误拿出来,那就不需要多线程了。到处都是慢代码。
tblRow [col.Name] = reader [col.Name];
SLOW。永远不要使用名称 - 获取循环外的索引,然后使用索引。这行对于eery行有2(!)字典查找,比行处理花费的时间更长。
DataTables / DataSet开始时效果很慢(糟糕的技术选择),但像这样的代码真的很慢。使用分析器查看其他不良元素。
答案 1 :(得分:1)
这可能不是您所追求的答案,但您是否尝试首先在发布模式下运行控制台应用程序,只需一个try语句,并在阅读器上使用索引?由于SQL Server将成为主要瓶颈,因此可能无法通过多线程来提高速度。
当然,如果您不太关心数据完整性(例如您的ID不是连续的),您可以更改插入的table locking类型并旋转3-4个线程以从某些点读取在表中。
答案 2 :(得分:0)
我认为您的用例不会从每个用户的并行中获益。此外,实现代码中使用的OleDbReader的原因也很难。
但是你可以做的是在新线程上安排插入,在SQL Server需要插入数据时,你的循环不会阻塞。
您可以使用Task.Factory.StartNew()
method进行此操作。但这会使错误处理变得更复杂,因为当插入失败时,您可能已经处理了更多数据,或者在最坏的情况下,已经有另一个线程正在等待数据库的新插入。
答案 3 :(得分:0)
如果您使用的是.NET 4,可以尝试使用TPL,并将foreach循环转换为类似
的内容Parallel.ForEach(table.Columns, col => {/*rest of function here */}