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

3

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

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

其他信息:集合已修改;枚举操作无法执行。

以下是显示异常的代码...

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是一个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个回答

16
foreach (PC_list x in onlinelist)
{            
     onlinelist.Remove(x); // cannot do this
}

这是问题的核心。在使用 foreach 迭代时,您无法从集合中删除项。您有以下几种选择:在循环之前制作本地列表的副本,遍历副本并从原始列表中删除,或者在完成原始循环后保持一个单独的要删除的项目列表。或者你可以切换到 for 循环,并以反向方式迭代,这允许你在进行迭代时从末尾删除项目。
除此之外,如果您不必使用 C# 1 / .NET 1.1 / Visual Studio 2003,建议您考虑从 ArrayList 切换到更强大的 List<T>,其中 T 是集合中对象的类型,在这种情况下,应该使用 List<PC_list>,可以在 System.Collections.Generic.List<T> 中找到它。
另外,由于您的问题标记为 multithreading,建议您查阅针对并发性构建的集合,可在 此处 找到相关信息。

4

在foreach块中,您不能修改onlinelist。这就是为什么会出现此错误的原因。

尝试这样做:

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);
        }

0

是的,你的逻辑有问题。你要求迭代器在列表中移动到x之后的下一个对象,但是你已经从列表中删除了x,所以不存在这样的东西。有很多解决方法,但传统的方法是在循环顶部删除前一个对象。(这仅适用于不在删除时重新组织的集合。)


1
这还不太行。当你在 foreach 循环中时,不能删除列表中的任何项。 - phoog

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接