我应该使用锁或ToList()

时间:2014-02-16 08:20:24

标签: c# collections locking

避免出现这个着名的错误:

  

收藏被修改;枚举操作可能无法执行

在迭代IEnumerator时,我应该按照this questions中的建议使用ToList(),还是应该在更新列表时使用lock

我担心的是ToList()每次只是创建一个新列表,而lock在更新列表时在某些点只会有一点延迟。

那么,我应该使用ToList()还是lock

1 个答案:

答案 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。我还建议确保在枚举时确实需要修改集合。在许多情况下(但不是全部),你可以不同地设计位以避免它首先出现。