【发布时间】:2018-03-16 18:16:07
【问题描述】:
由于 MicroSoft 所述的好处,我正在使用 Parallel.ForEach 实现大量 SQL SELECT 语句(数以千计)(顺便说一句:我现在找不到它,但我我很确定我在某处读到 Parallel.ForEach 在执行所有迭代之前不会返回控制权。这是真的吗?)
我从Parallel.Foreach SQL querying sometimes results in Connection 开始。我不想使用已接受的答案,因为它放弃了Parallel.ForEach,而只使用了Task.Run(或.Net 4.0 的Task Factory.StartNew)。同时,O.P. 使用“锁定”来同步更新到DataTable 的列表,我理解这可能会降低Parallel.ForEach 的效率。
所以,使用文章How to: Write a Parallel.ForEach Loop with Thread-Local Variables,我写了下面的稻草人代码。目标是将threadLocalDataTable(每个选择语句一个)累积到所有查询完成后返回的dataTableList。它可以工作,但我想知道localFinally 方法是否真的是线程安全的(请参阅带有注释//<-- the localFinally method in question 的代码行。注意:SqlOperation 类实现了连接字符串、输出数据表名称和选择查询字符串
public static IList<DataTable> GetAllData(IEnumerable<SqlOperation> sqlList)
{
IList<DataTable> dataTableList = new List<DataTable>();
dataTableList.Clear();
try
{
Parallel.ForEach<SqlOperation, DataTable>(sqlList, () => null, (s, loop, threadLocalDataTable) =>
{
DataTable dataTable = null;
using (SqlCommand sqlCommand = new SqlCommand())
{
using (SqlConnection sqlConnection = new SqlConnection(s.ConnectionString))
{
sqlConnection.Open();
sqlCommand.CommandType = CommandType.Text;
sqlCommand.Connection = sqlConnection;
sqlCommand.CommandText = s.SelectQuery;
SqlDataAdapter sqlDataAdapter = new SqlDataAdapter(sqlCommand);
dataTable = new DataTable
{
TableName = s.DataTableName
};
dataTable.Clear();
dataTable.Rows.Clear();
dataTable.Columns.Clear();
sqlDataAdapter.Fill(dataTable);
sqlDataAdapter.Dispose();
sqlConnection.Close();
}
}
return dataTable;
}, (threadLocalDataTable) => dataTableList.Add(threadLocalDataTable) //<-- the localFinally method in question
);
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString(), "GetAllData error");
}
return dataTableList;
}
【问题讨论】:
-
客户端中的并行任务不影响 SQL 服务器。查看 SQL 探查器。没有性能提升。
标签: c# thread-safety parallel.foreach