Maison >développement back-end >C++ >Comment gérer la «collection a été modifiée; l'opération d'énumération peut ne pas exécuter« Erreurs dans des environnements multithreads?
Adressant "Collection modifiée: l'opération d'énumération peut échouer" Erreurs
La collection d'erreur "a été modifiée; l'opération d'énumération peut ne pas s'exécuter" survient lorsqu'une collection est modifiée tout en étant itérée, conduisant à un comportement imprévisible. Cela se produit généralement dans des scénarios multithread où plusieurs threads accèdent et modifient simultanément la même collection.
Cette erreur spécifique se manifeste dans la méthode NotifySubscribers()
, où le dictionnaire subscribers
est accessible dans une boucle foreach
. Les modifications simultanées de ce dictionnaire (par exemple, les abonnements aux clients ou les désabonnements) invalident l'énumération.
Solution: implémentation de la sécurité du thread
Pour résoudre ce problème, la sécurité du fil pour le dictionnaire subscribers
est cruciale. Deux approches sont recommandées:
en utilisant ConcurrentDictionary
: Remplacez le dictionnaire standard par ConcurrentDictionary<TKey, TValue>
. Cette structure de données est intrinsèquement filiale, empêchant l'erreur.
Création d'une copie pour itération: Avant la boucle foreach
, créez une copie des valeurs du dictionnaire subscribers
à l'aide de subscribers.Values.ToList()
. Cela crée un instantané qui n'est pas affecté par les modifications ultérieures du dictionnaire d'origine, garantissant une énumération sûre.
Exemples de code:
Voici la méthode NotifySubscribers()
modifiée pour utiliser ConcurrentDictionary
:
<code class="language-csharp">public void NotifySubscribers(DataRecord sr) { foreach (Subscriber s in subscribers.Values) // subscribers is now a ConcurrentDictionary { try { s.Callback.SignalData(sr); } catch (Exception e) { DCS.WriteToApplicationLog(e.Message, System.Diagnostics.EventLogEntryType.Error); UnsubscribeEvent(s.ClientId); } } }</code>
Et voici la version utilisant ToList()
pour créer une copie sûre:
<code class="language-csharp">public void NotifySubscribers(DataRecord sr) { foreach (Subscriber s in subscribers.Values.ToList()) { try { s.Callback.SignalData(sr); } catch (Exception e) { DCS.WriteToApplicationLog(e.Message, System.Diagnostics.EventLogEntryType.Error); UnsubscribeEvent(s.ClientId); } } }</code>
En mettant en œuvre l'une ou l'autre de ces solutions, vous assurez la sécurité des threads et empêchez l'erreur "Collection a été modifiée ...", conduisant à un code plus robuste et fiable.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!