避免出现这个着名的错误:
收藏被修改;枚举操作可能无法执行
在迭代IEnumerator
时,我应该按照this questions中的建议使用ToList()
,还是应该在更新列表时使用lock
?
我担心的是ToList()
每次只是创建一个新列表,而lock
在更新列表时在某些点只会有一点延迟。
那么,我应该使用ToList()
还是lock
?
答案 0 :(得分:3)
您看到的错误告诉您在枚举时尝试修改集合。 lock
关键字适用于多线程情况,它确保您的唯一一个线程处于关键部分。它与“锁定”集合无关,因此您可以在修改它时对其进行枚举。
您看到的错误通常发生在下面的代码
中foreach(var item in items)
{
//Inside this loop now you are enumerating collection
//This means you can't add or delete anything from items
items.Add(newItem); //This will produce the error you are seeing
}
如果您有一个线程枚举集合,而其他线程在集合中添加或删除,则也可能发生此错误。因此,如果你知道你有多线程的情况,那么你可以使用lock
,虽然它有点棘手,可能会影响你的并发性能甚至导致竞争条件。对于多线程情况,仅使用ToList
可能是不够的,因为您在调用ToList
时需要确保只有一个线程可以访问集合。因此,您可能需要使用ToList
以及锁定,根据您的方案,它可能是更简单的选项。要查看如何执行线程安全修改而枚举的示例,请参阅以下答案:Making a "modify-while-enumerating" collection thread-safe。
如果您知道自己没有多个帖子,则ToList
可能是您唯一的选择,而您根本不需要lock
。我还建议确保在枚举时确实需要修改集合。在许多情况下(但不是全部),你可以不同地设计位以避免它首先出现。