System.InvalidOperationException:集合已被修改

ker*_*_xc 5 c# collections thread-safety

我在通过队列枚举时遇到以下异常:

System.InvalidOperationException:集合已被修改; 枚举操作可能无法执行

这是代码摘录:

1:    private bool extractWriteActions(out List<WriteChannel> channelWrites)
2:    {
3:        channelWrites = new List<WriteChannel>();
4:        foreach (TpotAction action in tpotActionQueue)
5:        {
6:            if (action is WriteChannel)
7:            {
8:                channelWrites.Add((WriteChannel)action);
9:                lock(tpotActionQueue)
10:               {
11:                  action.Status = RecordStatus.Batched;
12:               }
13:           }
14:       }
15:       return (channelWrites.Count > 0);
16:   }
Run Code Online (Sandbox Code Playgroud)

我想我理解了这个问题 - 改变哈希表action.Status = RecordStatus.Batched,这搞砸了枚举器上的MoveNext().问题是,我该如何正确实现"模式"?

Sar*_*els 8

我认为我foreach在Collection上使用循环时遇到类似的异常,我试图从Collection中删除项目(或者它可能是List,我不记得了).我最后通过使用for循环来绕过它.也许尝试以下内容:

for (int i=0; i<tpotActionQueue.Count(); i++)
{
    TpotAction action = tpotActionQueue.Dequeue();
    if (action is WriteChannel)
    {
        channelWrites.Add((WriteChannel)action);
        lock(tpotActionQueue)
        {
            action.Status = RecordStatus.Batched;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)


Sta*_* R. 6

您可以更改集合中项目的值.您获得的错误意味着添加或删除了一个项目,即:集合本身已被修改,而不是集合中的项目.这很可能是由另一个线程向此集合添加或删除项目引起的.

您应该在方法的开头锁定队列,以防止其他线程在您访问它时修改集合.或者您可以在调用此方法之前锁定集合.

private bool extractWriteActions(out List<WriteChannel> channelWrites)
    {
      lock(tpotActionQueue)
      {
        channelWrites = new List<WriteChannel>();
        foreach (TpotAction action in tpotActionQueue)
        {
            if (action is WriteChannel)
            {
                channelWrites.Add((WriteChannel)action);

                  action.Status = RecordStatus.Batched;

           }
        }
      }
       return (channelWrites.Count > 0);
   }
Run Code Online (Sandbox Code Playgroud)