介绍ADO.NET的DataTable/DataRow的线程安全
今天上午,他在和结果不一致(即,列值有时会出来空时,他们不应该是)一个问题向我报告的用户我们提供的一些并行执行代码作为内部框架的一部分。这段代码在过去一直很好,并没有被篡改最近,但它让我开始思考下面的代码片段:
代码示例
lock (ResultTable)
{
newRow = ResultTable.NewRow();
}
newRow["Key"] = currentKey;
foreach (KeyValuePair<string, object> output in outputs)
{
object resultValue = output.Value;
newRow[output.Name] = resultValue != null ? resultValue : DBNull.Value;
}
lock (ResultTable)
{
ResultTable.Rows.Add(newRow);
}
(无保证,编译,手-edited掩盖proprietery信息。)
说明
我们在欧锁定代码等地的这种级联型r系统,并且工作正常,但这是我遇到的与ADO .NET交互的第一个级联锁定代码。众所周知,框架对象的成员通常不是线程安全的(这种情况就是这种情况),但级联锁定应确保我们不会同时读取和写入ResultTable.Rows。我们很安全,对吧?
假设
好,级联锁码不保证我们不会从读取或在同一时间,我们在新的分配值列写ResultTable.Rows 行。如果ADO .NET使用某种缓冲区来分配不是线程安全的列值,即使涉及不同的对象类型(DataTable与DataRow),也会如此?
有没有人遇到过这样的事情?我想我会问在这里StackOverflow的打我的头这小时结束:)
结论
好之前,共识似乎是改变级联锁全锁已经解决了问题。这不是我预期的结果,但完整的锁定版本在经过很多很多很多测试之后并未产生问题。
教训:请谨慎使用您不能控制的API上使用的级联锁。谁知道可能会发生什么?
艾伦......我可以使用更多的信息。你是否以断开的方式使用DataSet对象?数据存储是什么以及如何安排更新? ADO.NET是一个很多头兽:) – Rusty 2010-05-19 20:37:34
很好的问题!是的,这是一个以断开方式使用的DataTable。在这种情况下没有数据存储(全部在内存中)。线程通过我们遍布各地使用的内部线程池的实例进行调度。在这种特殊情况下,线程池通过信号量在8个线程中被限制。 无论如何,我希望能够充分回答你的问题! – 2010-05-19 20:52:05
最优秀。我现在正在处理一些断开连接的数据集......我会尝试进行一些测试。 您正在运行3.5或4.0吗? – Rusty 2010-05-19 22:28:55