队列ForEach循环引发InvalidOperationException

问题描述

| 我以前从未真正使用过“ 0”,所以我可能会遗漏一些明显的东西。我正在尝试像这样(每帧)遍历
Queue<EnemyUserControl>
foreach (var e in qEnemy)
{
     //enemy AI code
}
当敌人死亡时,敌人用户控件会引发一个我订阅的事件,然后我执行此操作(队列中的第一个敌人是有意删除的):
void Enemy_Killed(object sender,EventArgs e)
{      
     qEnemy.Dequeue();

     //Added TrimExcess to check if the error was caused by NULL values in the Queue (it wasn\'t :))
     qEnemy.TrimExcess();
}
但是,在调用出队方法之后,我在
foreach
循环上得到了
InvalidOperationException
。当我改用
Peek
时,没有错误,因此它必须更改队列本身,因为Dequeue会删除对象。 我最初的猜测是,它抱怨我正在修改一个由Enumerator迭代的集合,但是出队列是在循环外部执行的? 有什么想法可能导致此问题吗? 谢谢     

解决方法

        您正在
foreach
循环内修改队列。这是导致异常的原因。 演示此问题的简化代码:
var queue = new Queue<int>();
queue.Enqueue(1);
queue.Enqueue(2);

foreach (var i in queue)
{
    queue.Dequeue();
}
可能的解决方案是添加
ToList()
,如下所示:
foreach (var i in queue.ToList())
{
    queue.Dequeue();
}
    ,        我知道这是一篇旧文章,但以下内容如何:
var queue = new Queue<int>();
queue.Enqueue(1);
queue.Enqueue(2);

while (queue.Count > 0)
{
  var val = queue.Dequeue();
}
干杯     ,        旧帖子,但以为我会提供更好的答案:
var queue = new Queue<int>();
queue.Enqueue(1);
queue.Enqueue(2);


while (queue?.Count > 0))
{
  var val = queue.Dequeue();
}
由于DarkUrse的原始答案使用了do / while,当尝试在空队列上出队时,如果队列为空,这将导致异常,因此还增加了针对空队列的保护     ,        这是枚举器的典型行为。大多数枚举器被设计为仅在基础集合保持静态时才能正常运行。如果在枚举集合时更改了集合,则由
foreach
块为您注入的下一个对
MoveNext
的调用将生成此异常。
Dequeue
操作显然会更改集合,这就是造成此问题的原因。解决方法是将要从目标集合中删除的每个项目添加到第二个集合中。循环完成后,您可以循环浏览第二个集合并从目标中删除。 但是,这至少可能有点尴尬,因为
Dequeue
操作只会删除下一项。您可能必须切换到允许任意删除的其他收集类型。 如果您要坚持使用
Queue
,则将被迫将每个项目出队,并有条件地重新排队那些不应删除的项目。您仍然需要第二个集合来跟踪可以从重新排队中省略的项目。     ,        遍历元素时,不能从集合中删除它们。 我找到的最佳解决方案是使用\“ List <> toDelete \”,然后将要删除的内容添加到该列表中。一旦foreach循环结束,您可以使用toDelete列表中的引用从目标集合中删除元素,如下所示:
foreach (var e in toDelete)
    target.Remove(e);
toDelete.Clear();
现在,由于这是一个队列,您可能只需要计算要以整数出队的次数,然后使用简单的for循环稍后再执行它们(在这方面,我没有太多的队列经验)。     ,        在哪里修改集合都没关系。如果在枚举成员时修改了集合,则会出现异常。您可以使用锁并确保在迭代时不修改集合,或者如果您使用的是.NET 4.0,则将collection17替换为ѭ20。     

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...