为什么SynchronizedCollection <t>没有锁定IEnumerable.GetEnumerator()</t>

时间:2009-12-16 21:55:40

标签: c#-3.0

为什么SynchronizedCollection<T>IEnumerable.GetEnumerator()

的显式实现中没有获得对SyncObj的锁定
  IEnumerator IEnumerable.GetEnumerator()
    {
        return this.items.GetEnumerator();
    }

隐式实现确实获得了对SyncOb的锁定(由反射器验证)。

在此集合的foreach循环期间可能会出现问题。一个线程可能已经获得了锁定而另一个可能尝试使用foreach读取它?

3 个答案:

答案 0 :(得分:4)

因为类无法知道何时使用迭代器完成客户端代码。这就是System.Collection类上的MSDN Library文档始终警告迭代集合不是线程安全的原因之一。

虽然他们似乎忘了在SynchronizedCollection的文章中提到它。具有讽刺意味......

答案 1 :(得分:1)

当某人使用迭代器时修改集合无论如何都是并发冲突。

你的选择是什么?在获取迭代器时锁定集合,在解析迭代器之前不解锁它?

答案 2 :(得分:1)

我将继续说这可能是实施中的错误( ed:或至少是不一致)。 Reflector精确显示您所看到的内容,除了SyncRoot之外,每个其他显式实现都会锁定IEnumerable.GetEnumerator()给定的内容。

也许你应该在Microsoft Connect提交一张票。

我认为隐式GetEnumerator()方法调用lock的原因是因为List<T>.GetEnumerator()创建了一个新的Enumerator<T>,它依赖于列表中的私有字段_version 。虽然我同意其他海报,但我没有看到锁定GetEnumerator()调用的用法,但由于Enumerator<T>的构造函数依赖于非线程安全字段,因此锁定是有意义的。或者至少与隐式实现保持一致。