關於DataTable內部索引已損壞的問題 System.Data.RBTree

一、錯誤提示:

最近,Winform程序在極其偶然的狀況下會遇到以下錯誤提示數組

Framework 版本: v4.0.30319
說明: 因爲未經處理的異常,進程終止。
異常信息: System.InvalidOperationException
堆棧:
   在 System.Data.RBTree`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].RBDeleteX(Int32, Int32, Int32)
   在 System.Data.RBTree`1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]].DeleteByIndex(Int32)
   在 System.Data.Index.RecordStateChanged(Int32, System.Data.DataViewRowState, System.Data.DataViewRowState, Int32, System.Data.DataViewRowState, System.Data.DataViewRowState)
   在 System.Data.DataTable.RecordStateChanged(Int32, System.Data.DataViewRowState, System.Data.DataViewRowState, Int32, System.Data.DataViewRowState, System.Data.DataViewRowState)
   在 System.Data.DataTable.SetNewRecordWorker(System.Data.DataRow, Int32, System.Data.DataRowAction, Boolean, Boolean, Int32, Boolean, System.Exception ByRef)
   在 System.Data.DataTable.SetNewRecord(System.Data.DataRow, Int32, System.Data.DataRowAction, Boolean, Boolean, Boolean)
   在 System.Data.DataRow.EndEdit()
   在 System.Data.DataRow.set_Item(System.Data.DataColumn, System.Object) 

相信有很多人遇到過這個問題,老王也被這個問題困擾了一個星期了。安全

差了很多資料,此問題基本與版本無關,由於1.0、1.一、2.0、3.五、4.0、4.5都是能夠重現問題的。多線程

 

二、致使「Datatable 的索引已損壞」發生的緣由有四種。

(1)在DataView.ListChanged 事件的時候改變值。這是不支持的。 

來看一下調用堆棧,若是你看到DataView.OnListChanged,你正在更改一個DataRow/Set/Table,這時極可能會發生索引損壞(即被DataRow.EndEdit拋出)。.net

簡短描述一下這個問題:內部索引獲得編輯out-of-order的消息。線程

解決方法-使用DataTable.RowChanged事件,而不是DataView.ListChanged事件。orm

 (2)當合並數據到已經存在的DataRow時候仍然有一些沒有修復的漏洞, 這個是在Added或者Deleted狀態下開始,並在Modified行狀態的時候結束。

當 LoadOption.PreserveChanges事件發生時,調用DataAdapter.Fill, DataSet.Load, DataTable.Load事件。對象

用DataSet.Merge, DataTable.Merge來刪除行。blog

用DataSet.Merge (DataRow[])添加行。排序

簡單描述問題:當DataTable讓DataView 「添加」而不是「修改」時,致使索引損壞。索引

 (3)多線程

DataSet/ DataTable和任何鏈接的對象都不是線程安全的。請確保您鎖定全部合適的對象。

個人問題屬於此類,由於我在多線程中都有操做DataTable,而後,看了這篇帖子,我在全部操做DataTable的地方都加入了Lock語句,而後問題解決了!

感謝此文做者 GR_king,原文網址:http://blog.51cto.com/gleolee/1911134

lock (datatable)
{
    針對datatable的操做
}

(4)當DataColumn.DataType是一個引用類型,而且值是被更改而不是被看成只讀類型來對待的時候。

例如:DataColumn.DataType是byte []類型和按照列排序的。若是在byte數組中的值改變而不是制定一個新的byte數組給DataRow,

那麼內部的索引不知道這樣的變化,而後損壞。這是在沒有通知內部索引的狀況下數據發生改變。

 

本文非原創,轉自:https://blog.csdn.net/deboywang/article/details/84070501

相關文章
相關標籤/搜索