我之前没有使用Queues<T>
任何真实的学位,所以我可能会遗漏一些明显的东西。我正在尝试迭代这样的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();
}
然而,在调用Dequeue方法之后,我在InvalidOperationException
循环上得到foreach
。当我使用Peek
时,没有错误,所以它必须对Queue本身的更改做一些事情,因为Dequeue删除了对象。
我最初的猜测是,它正在抱怨我正在修改一个由Enumerator迭代的集合,但是这个集合是在循环之外执行的吗?
任何可能导致此问题的想法?
由于
答案 0 :(得分:21)
我知道这是一个老帖子,但以下内容如何:
var queue = new Queue<int>();
queue.Enqueue(1);
queue.Enqueue(2);
while (queue.Count > 0)
{
var val = queue.Dequeue();
}
干杯
答案 1 :(得分:17)
您正在修改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();
}
答案 2 :(得分:1)
这是枚举器的典型行为。大多数枚举器只有在底层集合保持静态时才能正常运行。如果在枚举集合时更改了集合,则MoveNext
块为您注入的foreach
的下一次调用将生成此异常。
Dequeue
操作显然会改变集合,这就是造成问题的原因。解决方法是将要从目标集合中删除的每个项目添加到第二个集合中。循环完成后,您可以循环完成第二个集合并从目标中删除。
然而,这可能有点尴尬,至少,因为Dequeue
操作只删除下一个项目。您可能必须切换到允许任意删除的其他集合类型。
如果您想坚持使用Queue
,那么您将被迫出列每个项目,并有条件地重新排列那些不应删除的项目。您仍然需要第二个集合来跟踪可以从重新排队中省略的项目。
答案 3 :(得分:1)
旧帖子,但我想我会提供更好的答案:
var queue = new Queue<int>();
queue.Enqueue(1);
queue.Enqueue(2);
while (queue.Any())
{
var val = queue.Dequeue();
}
由于DarkUrse的回答可能会在队列为空时导致异常
答案 4 :(得分:0)
迭代时,您无法从集合中删除元素。
我找到的最佳解决方案是使用“List&lt;&gt; toDelete”并将要删除的内容添加到该列表中。 foreach循环结束后,您可以使用toDelete列表中的引用从目标集合中删除元素,如下所示:
foreach (var e in toDelete)
target.Remove(e);
toDelete.Clear();
既然这是一个Queue,你可能只需要计算你想要在一个整数中出队的次数,并使用一个简单的for循环来执行它们(我没有那么多的队列经验)方面)。
答案 5 :(得分:0)
修改集合的位置无关紧要。如果在枚举其成员时修改了集合,则会出现异常。您可以使用锁定并确保在设置时不会修改集合,或者使用.NET 4.0将Queue
替换为ConcurrentQueue
。