2010-12-15 32 views
6

Je reçois l'erreur suivante lorsque j'essaie de supprimer une ligne tout en la bouclant.Problème lors de la suppression d'une ligne dans la zone de données lors de l'énumération

C#: La collection a été modifiée; opération d'énumération peut ne pas exécuter

J'ai fait quelques recherches depuis un moment, et j'ai lu quelques messages similaires ici, mais je n'ai toujours pas trouvé la bonne réponse.

foreach (DataTable table in JobsDS.Tables) 
{ 

    foreach (DataRow row in table.Rows) 
    { 
    if (row["IP"].ToString() != null && row["IP"].ToString() != "cancelled") 
    { 
     string newWebServiceUrl = "http://" + row["IP"].ToString() + "/mp/Service.asmx"; 
     webService.Url = newWebServiceUrl; 
     string polledMessage = webService.mpMethod(row["IP"].ToString(), row["ID"].ToString()); 

     if (polledMessage != null) 
     { 
      if (polledMessage == "stored") 
      {    
       removeJob(id); 
      } 

     } 
    } 
} 

}

toute aide serait grandement appréciée

Répondre

14

Au lieu d'utiliser foreach, utilisez une boucle for inverse:

for(int i = table.Rows.Count - 1; i >= 0; i--) 
{ 
    DataRow row = table.Rows[i]; 
    //do your stuff 
} 

Retrait de la ligne modifie en effet la collection originale de lignes . La plupart des enquêteurs sont conçus pour exploser s'ils détectent que la séquence source a changé au milieu d'une énumération - plutôt que d'essayer de gérer toutes les étranges possibilités de changer quelque chose qui est en train de changer et d'introduire probablement des bugs très subtils. ne pas l'autoriser.

+0

comme un gant! thanx – hikizume

3

Vous ne pouvez pas modifier une collection à l'intérieur d'un foreach qui l'entoure. Au lieu de cela, vous devez utiliser une boucle for vers l'arrière.

3

Si vous souhaitez supprimer des éléments d'une boucle sur une liste d'éléments, l'astuce consiste à utiliser une boucle for, à partir du dernier élément et aller au premier élément.

Dans votre exemple:

int t_size = table.Rows.Count -1; 

for (int i = t_size; i >= 0; i--) 
{ 
    DataRow row = table.Rows[i]; 
    // your code ... 
} 

Edit: pas assez rapide :)

+0

Il n'y a pas de point dans une variable 't_size' séparée. – SLaks

+0

@SLaks: non, c'est juste pour être plus clair :) – LaGrandMere

+0

@SLaks Je ne pense pas qu'il y ait plus ou moins de point que votre commentaire –

0

Aussi, si vous dépendez de l'ordre que vous traitez les lignes et une boucle inverse ne fonctionne pas pour vous. Vous pouvez ajouter les lignes que vous souhaitez supprimer à une liste, puis, après avoir quitté la boucle foreach, vous pouvez supprimer les lignes ajoutées à la liste. Par exemple,

foreach (DataTable table in JobsDS.Tables) 
{ 
    List<DataRow> rowsToRemove = new List<DataRow>(); 
    foreach (DataRow row in table.Rows) 
    { 
    if (row["IP"].ToString() != null && row["IP"].ToString() != "cancelled") 
    { 
     string newWebServiceUrl = "http://" + row["IP"].ToString() + "/mp/Service.asmx"; 
     webService.Url = newWebServiceUrl; 
     string polledMessage = webService.mpMethod(row["IP"].ToString(), row["ID"].ToString()); 

     if (polledMessage != null) 
     { 
      if (polledMessage == "stored") 
      {     
       //removeJob(id); 
       rowsToRemove.Add(row); 
      } 

     } 
    } 
    } 
    rowsToRemove.ForEach(r => removeJob(r["ID"].ToString())); 
} 
0

D'une certaine façon removeJob(id) change l'un des IEnumerables votre énumération (table.Rows ou JobsDS.Tables, du nom de la méthode que je suppose que ce serait celui-ci), peut-être par l'intermédiaire DataBinding.

Je ne suis pas sûr que le for va fonctionner directement parce qu'il semble que vous supprimez un élément énuméré dans le foreach externe à l'intérieur du foreach interne. Il est difficile de dire sans plus d'informations sur ce qui se passe dans removeJob (id).