集合在datatable.Copy()上被修改了异常

时间:2012-06-20 16:17:33

标签: c# .net thread-safety

当我致电datatable.Copy()并且我不确定原因时,我收到以下异常。我应用了一个锁来避免这个问题,但它似乎没有解决它。异常不会一直发生,所以我知道它与线程有关。我误解了锁是如何工作的吗?

  

System.InvalidOperationException:修改了集合;枚举操作可能无法执行。     在System.Data.RBTree`1.RBTreeEnumerator.MoveNext()     在System.Data.DataTable.Copy()

代码:

DataTable dt;

lock (ClassName.datatable)
{
    dt = ClassName.datatable.Copy();
}

ClassName是一种类型,而不是一个对象(在我之前的一个问题中存在一些混淆)。

1 个答案:

答案 0 :(得分:3)

根据评论判断,您误解了lock的工作原理。这是一个协作方案,因此两个线程不能同时在同一个监视器上保持锁定。除非线程试图“输入”锁,使用lock语句或Monitor.Enter(和相关的调用),否则另一个线程持有锁的事实是无关紧要的。

这有点像没有锁的卫生间,而是一个“订婚”或“空置”的标志......没有人强迫要么自己改变标志,要么注意到它当前状态......但如果每个人同意同时执行这两项操作,则可以避免出现令人尴尬的情况。

我个人试图避免锁定任何其他代码可见的显示器,所以我可能会:

private readonly object tableLock = new objet();
private readonly DataTable table;

...

lock (tableLock)
{
    ...
}

你需要至少可能获得你使用表的无处不在的锁,当然如果你将它传递给其他可能存储对它的引用的方法,或者你给它的其他一些代码,你几乎无法控制它发生了什么。