介紹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