Le réponse acceptée à la question "Pourquoi ce code Parallel.ForEach gèle-t-il le programme?" conseille de remplacer l'utilisation de la liste par ConcurrentBag dans une application WPF.
Je voudrais savoir si un BlockingCollection peut être utilisé dans ce cas à la place?
Vous pouvez en effet utiliser un BlockingCollection
, mais cela ne sert à rien.
Tout d'abord, notez que BlockingCollection
est un wrapper autour d'une collection qui implémente IProducerConsumerCollection<T>
. Tout type qui implémente cette interface peut être utilisé comme stockage sous-jacent:
Lorsque vous créez un
BlockingCollection<T>
objet, vous pouvez spécifier non seulement la capacité limitée mais également le type de collection à utiliser. Par exemple, vous pouvez spécifier unConcurrentQueue<T>
objet pour le comportement premier entré, premier sorti (FIFO), ou unConcurrentStack<T>
objet pour le comportement dernier entré, premier sorti (LIFO). Vous pouvez utiliser n'importe quelle classe de collection qui implémente leIProducerConsumerCollection<T>
interface. Le type de collection par défaut pourBlockingCollection<T>
estConcurrentQueue<T>
.
Ceci comprend ConcurrentBag<T>
, ce qui signifie que vous pouvez avoir un sac simultané bloquant. Alors, quelle est la différence entre un simple IProducerConsumerCollection<T>
et une collection bloquante? La documentation de BlockingCollection
dit (soulignement le mien):
BlockingCollection<T>
est utilisé comme wrapper pour unIProducerConsumerCollection<T>
instance, permettant de bloquer les tentatives de suppression de la collection jusqu'à ce que les données soient disponibles pour être supprimées . De même, unBlockingCollection<T>
peut être créé pour appliquer une limite supérieure sur le nombre d'éléments de données autorisés dans leIProducerConsumerCollection<T>
[...]
Étant donné que dans la question liée, il n'est pas nécessaire de faire l'une ou l'autre de ces choses, l'utilisation de BlockingCollection
ajoute simplement une couche de fonctionnalités qui n'est pas utilisée.
List<T>
est une collection conçue pour être utilisée dans des applications à un seul thread.
ConcurrentBag<T>
est un sous-type de ConcurrentCollection<T>
conçu pour simplifier l'utilisation des collections dans des environnements multi-threads. Si vous utilisez ConcurrentCollection, vous n'aurez pas à verrouiller votre collection pour éviter la corruption par d'autres threads. Vous pouvez insérer ou prendre des données de votre collection sans avoir besoin d'écrire des codes de verrouillage spéciaux.
BlockingCollection<T>
est conçu pour supprimer l'exigence de vérifier si de nouvelles données sont disponibles dans la collection partagée entre les threads. s'il y a de nouvelles données insérées dans la collection partagée, votre thread consommateur se réveillera immédiatement. Vous n'avez donc pas à vérifier si de nouvelles données sont disponibles pour le thread consommateur à certains intervalles de temps, généralement dans une boucle while.Oui, vous pouvez utiliser BlockingCollection
pour cela. finishedProxies
serait défini comme:
BlockingCollection<string> finishedProxies = new BlockingCollection<string>();
et pour ajouter un article, vous écririez:
finishedProxies.Add(checkResult);
Et quand c'est fait, vous pouvez créer une liste à partir du contenu.