web-dev-qa-db-fra.com

Comment supprimer tous les éléments de ConcurrentBag?

Comment effacer le ConcurrentBag? il n'a pas de méthode comme Clear ou RemoveAll...

67
PawanS
T someItem;
while (!myBag.IsEmpty) 
{
   myBag.TryTake(out someItem);
}
33
Daniel A. White

Mise à jour 10/03/2017: Comme le souligne @Lou correctement, l'affectation est atomique. Dans ce cas, la création de ConcurrentBag ne sera pas atomique, mais en mettant cette référence dans la variable sera sera atomique - donc verrouillable ou Interlocked.Exchange autour n'est pas strictement requis.

Quelques lectures supplémentaires:

l'affectation de référence est atomique, alors pourquoi est-ce que Interlocked.Exchange (ref Object, Object) est nécessaire?

n threads d'affectation de référence est-il sûr?


Vous pouvez toujours verrouiller l'accès au sac lui-même et en créer une nouvelle instance. Les articles dans le sac seront alors éligibles pour GC si rien d'autre ne les retient:

lock (something)
{
    bag = new ConcurrentBag();
}

Ou comme le souligne Lukazoid:

var newBag = new ConcurrentBag();
Interlocked.Exchange<ConcurrentBag>(ref bag, newBag);

Un moyen facile de regrouper le contenu, cependant, cela suppose que chaque fois qu'un élément veut accéder, il obtient également le verrou - cela pourrait être coûteux et pourrait annuler le réglage des performances qui est entré dans le ConcurrentBag lui-même.

Si vous savez que rien d'autre n'accédera au sac en ce moment, faites-le avec des ailes et ne le verrouillez pas :-)

58
Adam Houldsworth

La réponse sélectionnée est en quelque sorte une solution de contournement, donc j'ajoute ma propre solution de contournement.

Ma solution était de regarder toutes les collections disponibles dans l'espace de noms System.Collections.Concurrent pour en trouver une où il était trivial d'effacer tous les éléments de la collection.

La classe ConcurrentStack a une méthode Clear () qui supprime tous les éléments de la collection. En fait, c'est la seule collection de l'espace de noms (actuellement) qui le fasse. Oui, vous devez Push(T element) au lieu de Add(T element), mais franchement, cela vaut le temps gagné.

20
Will

Vous pouvez supprimer un objet un par un dans une boucle:

object result;
while (bag.TryTake(out result));

Notez que le sac n'est pas garanti d'être vide après cette boucle, car les éléments peuvent être ajoutés une fois la boucle terminée et avant la prochaine instruction par un thread différent.

9
gor

Dans un esprit de contournement .. ConcurrentDictionary<T, bool> a un Clear atomique, mais vous permet également de vérifier rapidement si une clé existe. "Rapidement" est bien sûr un terme relatif, mais en fonction de votre utilisation, il peut être plus rapide que d'énumérer une grande pile.

6
OlduwanSteve