Alb*_*bic 26 c# ienumerable yield yield-return
我有以下代码:
private Dictionary<object, object> items = new Dictionary<object, object>;
public IEnumerable<object> Keys
{
get
{
foreach (object key in items.Keys)
{
yield return key;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是线程安全的吗?如果不是我必须lock围绕循环或yield return?
这就是我的意思:
KeysThread1 访问属性,而Thread2将一个项添加到基础字典.Thread1是否受Thread2的影响?
Jon*_*eet 20
什么是线程安全的意思?
当你在迭代它时,你当然不应该更改字典,无论是否在同一个线程中.
如果通常在多个线程中访问字典,则调用者应取出一个锁(覆盖所有访问的同一个锁),以便它们可以在迭代结果的过程中锁定.
编辑:要响应您的编辑,它不会与锁定代码对应.迭代器块没有自动取出锁定 - 它怎么会知道syncRoot呢?
而且,只是锁定返回IEnumerable<TKey>也不会使它成为线程安全的 - 因为锁只会影响它返回序列的时间段,而不会影响它被迭代的时间段.
Jus*_*ner 18
查看这篇文章,了解幕后发生的yield关键字:
简而言之 - 编译器接受您的yield关键字并在IL中生成一个完整的类来支持该功能.您可以在跳转后查看页面并查看生成的代码...并且该代码看起来像跟踪线程ID以保证安全.
Alb*_*bic 10
好的,我做了一些测试,得到了一个有趣的结果.
它似乎更多是底层集合的枚举器而不是yield关键字的问题.枚举器(实际上是它的MoveNext方法)抛出(如果正确实现),InvalidOperationException因为枚举已更改.根据MoveNext方法的MSDN文档,这是预期的行为.
因为通过集合枚举通常不是线程安全的,yield return所以也不是.