【问题标题】:Collection was modified; enumeration operation may not execute. C# [duplicate]收藏已修改;枚举操作可能无法执行。 C# [重复]
【发布时间】:2011-12-07 09:33:19
【问题描述】:

我需要帮助。我正在使用一个数组列表,突然我收到了这个错误。

在 mscorlib.dll 中发生了“System.InvalidOperationException”类型的未处理异常

附加信息:收藏已修改;枚举操作可能无法执行。

这是显示异常的代码...

foreach (PC_list x in onlinelist) {
  if ((nowtime.Subtract(x.time)).TotalSeconds > 5) {
    Invoke(new MethodInvoker(delegate {
      index = Main_ListBox.FindString(x.PcName);
      if(index != ListBox.NoMatches)
      Main_ListBox.Items.RemoveAt(index);
    }));
    onlinelist.Remove(x);
    //Thread.Sleep(500);
  }
}

在哪里

public class PC_list {
    public string PcName;
    public string ip;
    public string status;
    public string NickName;
    public DateTime time;

}

注意事项:

  • onlinelist 是一个数组列表
  • nowtime 和 x.time 是 DateTime。

调用堆栈

mscorlib.dll!System.Collections.ArrayList.ArrayListEnumeratorSimple.MoveNext() + 0x122 bytes    
BlueBall.exe!BlueBall.BlueBall.clean_arraylist() Line 74 + 0x1a8 bytes  C#
BlueBall.exe!BlueBall.BlueBall.server() Line 61 + 0x8 bytes C#
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart_Context(object state) + 0x63 bytes   
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state, bool ignoreSyncCtx) + 0xb0 bytes    
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x2c bytes    
mscorlib.dll!System.Threading.ThreadHelper.ThreadStart() + 0x44 bytes   
[Native to Managed Transition]

【问题讨论】:

    标签: c# .net multithreading invoke


    【解决方案1】:
    foreach (PC_list x in onlinelist)
    {            
         onlinelist.Remove(x); // cannot do this
    }
    

    这是问题的核心。当您在 foreach 中迭代它时,您无法从集合中删除一个项目。您的选择是在循环之前制作列表的本地副本,遍历副本,然后从原始列表中删除。或者,您可以保留一个单独的项目列表,以在完成原始循环之后删除。或者,您可以切换到 for 循环并向后迭代它,这样您就可以随时从 end 中删除项目。

    当您在这里时,如果您没有被 C# 1 / .NET 1.1 / Visual Studio 2003 困住,您可能需要考虑从ArrayList 切换到更强大的List<T>,其中T 是集合中对象的类型。在您的情况下,那将是List<PC_list>。你可以在System.Collections.Generic.List<T>找到它。

    由于您的问题被标记为multithreading,因此咨询collections built with concurrency in mind 也是一个明智的主意。

    【讨论】:

      【解决方案2】:

      您不能在 foreach 块中修改在线列表。这就是您收到此错误的原因。 试试这个:

      ArrayList RemoveList = new ArrayList();
      foreach (PC_list x in onlinelist)
                  {
                      if ((nowtime.Subtract(x.time)).TotalSeconds > 5)
                      {
                          Invoke(new MethodInvoker(delegate
                          {
                              index = Main_ListBox.FindString(x.PcName);
                              if(index != ListBox.NoMatches)
                                  Main_ListBox.Items.RemoveAt(index);
                          }));
      
                          RemoveList.Add(x);
                          //Thread.Sleep(500);
                      }
                  }
      foreach (PC_list x in RemoveList)
              {
                      onlinelist.Remove(x);
              }
      

      【讨论】:

        【解决方案3】:

        是的,你的逻辑是错误的。您要求迭代器移动到列表中x 之后的下一个对象,但是您已经从列表中删除了x,所以没有这样的事情。有很多变通方法,但传统的方法是删除循环顶部的 previous 对象。 (这仅适用于不重新组织删除的集合。)

        【讨论】:

        • 不完全是。在 foreach 循环中,您无法从列表中删除任何项目。
        猜你喜欢
        • 1970-01-01
        • 2012-04-01
        相关资源
        最近更新 更多