收集被修改;枚举操作可能无法执行。 C#

时间:2011-10-14 00:35:27

标签: c# .net multithreading invoke

我需要帮助。我正在和一个arraylist一起工作,突然间我得到了这个错误。

  

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;

}

注意:

  • 在线列表是一个arraylist
  • 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]

3 个答案:

答案 0 :(得分:15)

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>,其中{ {1}}是集合中对象的类型。在您的情况下,那将是T。您可以在List<PC_list>找到它。

由于您的问题被标记为System.Collections.Generic.List<T>,因此咨询collections built with concurrency in mind也是明智之举。

答案 1 :(得分:4)

您无法修改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);
        }

答案 2 :(得分:0)

是的,你的逻辑被打破了。您要求迭代器移动到列表中x之后的下一个对象,但您已从列表中删除x,因此没有这样的事情。有很多变通方法,但传统的方法是删除循环顶部的之前的对象。 (这仅适用于未在删除时重新组织的集合。)