IT分享网

搜索
热搜: 活动 交友 discuz
查看: 1340|回复: 0

[BUG异常] 关于DataTable内部索引已损坏的解决办法

[复制链接]
发表于 2017-2-14 10:43:16 | 显示全部楼层 |阅读模式
个问题困扰了我很久,我想很多用.Net2.0的人也有碰到过。错误信息如下:
我用静态DataTable对象记录用户上线下线,一开始没有问题,大概半天以后出现一下错误,也不知道是什么问题,一旦出现这个问题,程序就挂掉了,即使用了try和catch也不行。错误如下:
---------------------------------------------------------------------------------------
DataTable 内部索引已损坏:“5”。
说明: 执行当前 Web 请求期间,出现未处理的异常。请检查堆栈跟踪信息,以了解有关该错误以及代码中导致错误的出处的详细信息。
异常详细信息: System.InvalidOperationException: DataTable 内部索引已损坏:“5”。
源错误:
执行当前 Web 请求期间生成了未处理的异常。可以使用下面的异常堆栈跟踪信息确定有关异常原因和发生位置的信息。
堆栈跟踪:

[InvalidOperationException: DataTable 内部索引已损坏:“5”。]
   System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 position) +431
   System.Data.RBTree`1.RBInsert(Int32 root_id, Int32 x_id, Int32 position) +846
   System.Data.RBTree`1.Insert(K item) +24
   System.Data.Index.InitRecords(IFilter filter) +1691978
   System.Data.Index..ctor(DataTable table, Int32[] ndexDesc, IndexField[] indexFields, DataViewRowState recordStates, IFilter rowFilter) +175
   System.Data.Select.CreateIndex() +1199
   System.Data.Select.SelectRows() +267
   System.Data.DataTable.Select(String filterExpression) +65
   MsgService.MyServer.checkUserExist(String UserID, String Domain) +167
   MsgService.Migrated_Ref.addUser() +132
   MsgService.Migrated_Ref.Page_Load(Object sender, EventArgs e) +292
   System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e) +15
   System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e) +34
   System.Web.UI.Control.OnLoad(EventArgs e) +99
   System.Web.UI.Control.LoadRecursive() +47
   System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +1061


--------------------------------------------------------------------------------
版本信息: Microsoft .NET Framework 版本:2.0.50727.42; ASP.NET 版本:2.0.50727.42



也在CSDN上面发了帖子,但是一直没有解决,后来在MSDN上面寻到了解决方法,放上来让大家给大家参考。
解决的办法其实很简单,只要了解出错原因。
一般我们会使用DataTable.Select()方法来筛选数据,而DataTable会在执行Select()方法的时候系统会默认创建一个DataView,而DataView创建的时候会创建内部索引,如果这个时候数据被操作(添加,删除),那么内部索引就会被破坏,从而出错。大概是这个意思吧,不知道有没有说错。所以解决的方法也很简单,就是新建一个DataView,并在创建DataView的时候锁定DataTable。
DataView myDV;
lock(myTable)
{
    myDV=new DataView(myTable,"过滤","排序",DataViewRowState.CurrentRows);

    //数据操作
}
原文如下:
A DataTable is thread safe for read operations but not for write operations.
So this means you can store a DataTable in the cache and extract it and use it in a read only fashion and it will work fine.
However, creating a DataView on a DataTable is a write operation on a DataTable.  Most people don't know this, and its not very intuitive so I don't blame them for not knowing this.
What happens when you create a DataView on a DataTable is the DataView will create an index on the DataTable and this index is stored in the DataTable.  The reason for this is performance, for example if you create a DataView saying "F1=1" as the criteria, this creates an internal index on the DataTable to locate this information.  Later on if you create another DataView with the same criteria, the index is reused, so this improves performance.   However the fact that these indexes are stored inside the DataTable means that these are write operations to the DataTable and thus they are not thread safe.
So if you are creating random DataViews on the DataTable you are constantly creating new indexes.  If you are creating the same type of DataView over and over you are constantly reusing existing index.
So unfortunately you need to serialize the creating of DataViews over the DataTable.
You could do this for example to avoid the problem:
lock(myDataTableFromCache)
{
dv = new DataView(myDataTableFromCache,...);
}
So lock using the DataTable as the locking object and lock when creating the DataView should solve the problem.



今天写程序遇见一个错误,错误是 “DataTable 内部索引已损坏:“13””。

程序是在一个线程里不停的对绑定在gridcontrol上的datatable进行添加行操作,运行一段时间就出错。


在网上搜了下,csdn的孟子大哥说是


由于性能原因,DataTable   没有设计成线程安全的,解决这个问题,可以在修改数据的时候采用lock语句

这里的修改包括:
1,添加,删除,修改DataTable的行
2,使用DataTable   的Select方法选择行,这会通过创建索引从而修改DataTable   
3,在DataTable上创建DataViews   ,也会导致重建索引
4,修改Sort属性也会导致DataTable的修改。


所以我就用lock语句,但是发现lock语句没有什么用,lock了一样的还是要出这个错误。lock修改后如下:


lock( m_BindDTable)

{

m_BindDTable.Rows.Add(dr);

}


后面我改成

    m_BindDTable.BeginLoadData();
     m_BindDTable.Rows.Add(dr);
     m_BindDTable.EndLoadData();
     m_BindDTable.AcceptChanges();


错误便没有出现异常了。具体详细的原理我说不上,但事实就是错误没有了。

错误原理估计是在添加行时,datatable内部对它进行了排序,操作太快了从而出错。



写这篇博客的时候,我又试了下,把我添加的语句注释了,结果错误又没有出现了,郁闷,不知道怎么回事。只不过不管了,我还是把代码加上去再说,免得后面再次出现。


希望我的方法能帮助出现过这个问题的朋友






您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

GMT+8, 2019-10-19 07:25 , Processed in 0.796854 second(s), 28 queries .

  

QQ|Archiver|手机版|小黑屋|IT分享网 ( 苏ICP备15049123号-2 )  

GMT+8, 2019-10-19 07:25 , Processed in 0.796854 second(s), 28 queries .

Powered by Discuz! X3.2 Designed by 999test.cn

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表