DataTable 集合已修改;枚举操作可能无法执行

时间:2021-05-11 00:59:11
声明了两个个DataTable 开启了两个线程
线程1控制 dt0,不断的刷新给值
线程2控制dt1,从dt0中筛选有效数据,然后给值


现在在线程2中,出现了  集合已修改;枚举操作可能无法执行 
猜测问题出现应该是   数据量超过一定数量后在还未筛选赋值完成的时候线程1更改了dt0;

问:如果对于这个问题不处理会有什么其他的相关问题出现?

9 个解决方案

#1


都没人回答?

#2


dt0在线程1修改的时候线程2正在从dt0中获取数据引起的;做对dt0做个锁,某一刻只能有一个线程操作,只有一个线程用完解锁后另外一个线程才能操作。

#3


引用 2 楼 thinkingforever 的回复:
dt0在线程1修改的时候线程2正在从dt0中获取数据引起的;做对dt0做个锁,某一刻只能有一个线程操作,只有一个线程用完解锁后另外一个线程才能操作。


不能这样,dt0是必须实时的获取数据,因为不确定数据时什么时候发送,而且发送过后就被销毁

#4


那就这样,在线程2访问dt0时,先创建一个新的dataset 把dt0的数据merge到新的dataset中,线程2操作新dataset。

#5


DataTable 在遍历的时候遭到修改就会出现问题的

类似于
foreach(var item in items)
{
     item = "修改值";
}
绝对出错

#6


如果你有代码:
foreach (DataRow dr in dt.Rows)
{
    ...
}
这样的代码。那么你需要修改为:
private object lockobject = new object(); //写在类定义中。

lock (lockobject)
{
    foreach (DataRow dr in dt.Rows)
    {
        ...
    }
}

#7


如果你在遍历中有耗时的操作,同时你不在乎这个遍历的过程中集合是否发生变化,你可以先复制一份快照:

private object lockobject = new object(); //写在类定义中。

DataRow[] snapshot;
lock (lockobject)
{
    snapshot = dt.Rows.Cast<DataRow>().ToArray();
}
foreach (DataRow dr in snapshot)
{
    ...
}

#8


引用 3 楼 LJ_liujue 的回复:
Quote: 引用 2 楼 thinkingforever 的回复:

dt0在线程1修改的时候线程2正在从dt0中获取数据引起的;做对dt0做个锁,某一刻只能有一个线程操作,只有一个线程用完解锁后另外一个线程才能操作。


不能这样,dt0是必须实时的获取数据,因为不确定数据时什么时候发送,而且发送过后就被销毁


实时跟 lock 是两码事, lock 完全能够满足你的需要

#1


都没人回答?

#2


dt0在线程1修改的时候线程2正在从dt0中获取数据引起的;做对dt0做个锁,某一刻只能有一个线程操作,只有一个线程用完解锁后另外一个线程才能操作。

#3


引用 2 楼 thinkingforever 的回复:
dt0在线程1修改的时候线程2正在从dt0中获取数据引起的;做对dt0做个锁,某一刻只能有一个线程操作,只有一个线程用完解锁后另外一个线程才能操作。


不能这样,dt0是必须实时的获取数据,因为不确定数据时什么时候发送,而且发送过后就被销毁

#4


那就这样,在线程2访问dt0时,先创建一个新的dataset 把dt0的数据merge到新的dataset中,线程2操作新dataset。

#5


DataTable 在遍历的时候遭到修改就会出现问题的

类似于
foreach(var item in items)
{
     item = "修改值";
}
绝对出错

#6


如果你有代码:
foreach (DataRow dr in dt.Rows)
{
    ...
}
这样的代码。那么你需要修改为:
private object lockobject = new object(); //写在类定义中。

lock (lockobject)
{
    foreach (DataRow dr in dt.Rows)
    {
        ...
    }
}

#7


如果你在遍历中有耗时的操作,同时你不在乎这个遍历的过程中集合是否发生变化,你可以先复制一份快照:

private object lockobject = new object(); //写在类定义中。

DataRow[] snapshot;
lock (lockobject)
{
    snapshot = dt.Rows.Cast<DataRow>().ToArray();
}
foreach (DataRow dr in snapshot)
{
    ...
}

#8


引用 3 楼 LJ_liujue 的回复:
Quote: 引用 2 楼 thinkingforever 的回复:

dt0在线程1修改的时候线程2正在从dt0中获取数据引起的;做对dt0做个锁,某一刻只能有一个线程操作,只有一个线程用完解锁后另外一个线程才能操作。


不能这样,dt0是必须实时的获取数据,因为不确定数据时什么时候发送,而且发送过后就被销毁


实时跟 lock 是两码事, lock 完全能够满足你的需要

#9