2011-10-14 3 views
1

J'ai besoin d'aide. Je travaille avec un arrayliste, et soudainement je reçois cette erreur.La collection a été modifiée; l'opération d'énumération peut ne pas s'exécuter. C#

Une exception non gérée du type 'System.InvalidOperationException' a eu lieu dans mscorlib.dll

Informations complémentaires: Collection a été modifiée; l'opération d'énumération peut ne pas s'exécuter.

Voici le code où il montre l'exception ...

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; 

} 

Notes:

  • onlinelist est un arraylist
  • nowtime et x.time sont DateTime.

Appel Stack

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] 

Répondre

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

C'est le cœur du problème. Vous ne pouvez pas supprimer un élément d'une collection lorsque vous l'exécutez dans un foreach. Vos options sont de faire une copie locale de la liste avant la boucle, boucle sur la copie, et supprimer de l'original. Ou vous pouvez conserver une liste distincte d'éléments à supprimer après vous terminez la boucle d'origine. Ou vous pouvez passer à une boucle for et la parcourir en arrière, ce qui vous permet de supprimer des éléments de l'et de au fur et à mesure.

Pendant que vous êtes ici, si vous n'êtes pas coincé travailler avec C# 1/.NET 1.1/Visual Studio 2003, vous voudrez peut-être envisager de passer de ArrayList au plus fort List<T>, où T est le type de l'objet la collection. Dans votre cas, ce serait un List<PC_list>. Vous pouvez le trouver au System.Collections.Generic.List<T>.

Et puisque votre question est étiquetée multithreading, il serait également une bonne idée de consulter le collections built with concurrency in mind.

0

Oui, votre logique est brisée. Vous demandez à l'itérateur de passer à l'objet suivant après x dans la liste, mais vous avez supprimé x de la liste, il n'y a donc rien de tel. Il existe de nombreuses solutions de contournement, mais la manière traditionnelle de le faire est de supprimer l'objet précédent en haut de la boucle. (Cela ne fonctionne que pour les collections qui ne se réorganisent pas lors des suppressions.)

+1

Ce n'est pas tout à fait ça. Vous ne pouvez supprimer aucun élément de la liste lorsque vous êtes dans la boucle foreach. – phoog

4

Vous ne pouvez pas modifier la liste des composants dans un bloc foreach. C'est pourquoi vous obtenez cette erreur. Essayez ceci:

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