DataTable多線程操作報錯情況


 

最近在寫一個http接口時用了DataTable這個強大的利器,接口用瀏覽器跑起來沒任何問題。當時也沒考慮並發問題,后來用一個壓力測試工具做大並發測試,1000+/s次速度測試。發現程序報錯了。程序報錯了第一反應還是去檢查代碼,是不是代碼出現問題。發現邏輯都是對的,然后用瀏覽器打開接口,發現一切OK;然后心想肯定是並發時多個線程操作導致的。

 

我們都知道在多線程的時候不同的線程訪問同一個資源的時候,用lock方法來達到線程同步,也就是同一個時刻同一個資源只能被一個線程操作。

我開始在操作DataTable的函數前面加上:

1 object oblock = new object();
2 
3 lock(oblock)
4 {
5     //我的dataTable對rows操作的代碼
6 }

信心滿滿的開始繼續用壓力測試工具來測試。結果還是報錯;因為是並發操作你幾乎不能用vs進行斷點調試;所以也不好找到具體的錯誤在什么地方。然后就try catch 打印錯誤日志找到具體異常原因和所在代碼行。提示的錯誤有時候都不盡相同;有“內部索引損壞”、"在位置0處沒有任何行" 等等。加了lock還報錯就感覺挺納悶的;當這段代碼被鎖定以后應該是不會被其他線程操作,也就不會導致行的索引出現問題。

 

后來找些資料發現,因為我們平時對DataTable的操作基本是Rows操作,所以我上面lock的代碼里面只鎖定了DataTable的Rows;但是因為我沒有操作Columns,所以其他線程還可以訪問DataTable的Columns集合。但是Rows是共享一個Columns的;罪魁禍首應該是沒有鎖住Columns導致的。

解決方法:

通過百度知道.Net里DataTable.Rows集合上提供.SyncRoot同步對象,正是為了在多線程環境下鎖住DataTable中的Rows集合同時也鎖住了Columns集合。

所以我們只需要在要操作DataTable代碼的前面加上:

 
         
1 //你要操作的 DataTable 2 DataTable dtb = new DataTable(); 3 lock(dtb.Rows.SyncRoot) 4 { 5 //你的DataTable處理代碼 6 }


注:並不是所有DataTable在多線程操作是都會報錯;視具體情況而定。但是為了線程安全在多線程下操作是最好加上Rows.SyncRoot鎖。

 
        

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM