Quelle collection System.Collections.Concurrent .NET 4.0 ajoutée à la fonctionnalité .NET 3.0 SynchronizedCollection?

.NET 4.0 a introduit l’espace de noms System.Collections.Concurrent :

“L’espace de noms System.Collections.Concurrent fournit plusieurs classes de collection sécurisées pour les threads qui doivent être utilisées à la place des types correspondants dans les espaces de noms System.Collections et System.Collections.Generic lorsque plusieurs threads accèdent simultanément à la collection”

  • BlockingCollection classe
  • ConcurrentBag class
  • Classe ConcurrentQueue
  • ConcurrentDictionary classe
  • OrderablePartitioner classe
  • Classe de Partitioner
  • IProducerConsumerCollection

La classe SynchronizedCollection (disponible depuis .NET 3.0):

“Fournit une collection thread-safe qui contient des objects d’un type spécifié par le paramètre générique en tant qu’éléments”

… est dans l’espace de noms System.Collections.Generic .

Alors, pourquoi la classe SynchronizedCollection -elle thread-safe mais pas concurrente?

Qu’est-ce qui rend spécifiquement la classe générique SynchronizedCollection différente et incompatible avec des collections de celles de System.Collections.Concurrent ?

Mise à jour: Permettez-moi de reformuler la question: quel est le dénominateur commun et la nouvelle fonctionnalité distinctive de toutes les collections génériques appartenant à l’espace de noms System.Collections.Concurrent , qui est absent (et impossible lors de l’utilisation) de la classe générique SynchronizedCollection ?

J’ai changé le titre en “Quelle collection System.Collections.Concurrent .NET 4.0 ajoutée dans la fonctionnalité de .NET 3.0 SynchronizedCollection ?”. Mais surtout, je suis curieux de savoir ce qui rendait impossible la réalisation de .NET 3.0.

Update2 : À propos de la note:

“Cette question peut déjà avoir une réponse ici:

Quelle est la différence entre SynchronizedCollection et les autres collections simultanées? ”

La réponse est confuse dans le contexte de ma question : les nouvelles fonctionnalités sont-elles évolutives (utilisation des fonctionnalités antérieures à .NET 4.0) ou révolutionnaires (non disponibles dans les versions antérieures à .NET 4.0)?

L’accent principal de .NET 4.0 était la concurrence. Microsoft a introduit l’espace de noms System.Threading.Tasks dans .NET 4.0. Il était donc logique d’append également l’espace de noms System.Collections.Concurrent. Comme mentionné précédemment, les collections de System.Collections.Concurrent sont très performantes car elles sont implémentées sans locking. Ce n’est pas une tâche facile et je pense que c’est la raison pour laquelle Microsoft a estimé qu’elle appartenait à une nouvelle version majeure de .NET plutôt qu’à une actualisation de .NET 3.x. Autant que je sache, le comportement sans locking est, entre autres, mis en œuvre à l’aide de la version générique d’ Interlocked.CompareExchange, également nouvelle pour .NET 4.0.

Si vous souhaitez savoir comment implémenter les classes de System.Collections.Concurrent, je vous recommande de lire le livre de Joe Duffy “Concurrent Programming on Windows” qu’il avait écrit avant la publication de .NET 4.0. Le livre montre comment certaines des collections simultanées sont mises en œuvre.

Les classes précédentes de la collection thread-safe ont un défaut assez important, elles ne peuvent pas être itérées de manière thread-safe. Il est en général très difficile de rendre le thread-safe itératif, il n’existe aucun moyen propre de créer un code qui utilise un iterator prenant en compte les éléments ajoutés ou supprimés d’une collection alors que le code l’itère. Le seul moyen réellement sûr est de verrouiller l’access à la collection pendant l’itération. C’est très indésirable, un tel verrou sera généralement maintenu pendant très longtemps. La meilleure façon de procéder consiste à créer une copie de la collection, copie qui ne sera pas modifiée et qui pourra toujours être itérée en toute sécurité. Personne n’aime l’exigence de stockage O (n) de cette solution.

La méthode Synchronized () dans les classes de la collection .NET 1.0 était particulièrement gênante. Microsoft n’a pas caché qu’itérer n’était pas thread-safe. Ils ont même ajouté du code pour détecter l’incident, il lève une exception lorsqu’un thread a modifié la collection. Cette exception ne se produit cependant pas assez souvent et les programmeurs .NET déconcertés qui n’ont pas réussi à lire l’étiquette d’avertissement et se sont contentés de supposer qu’une collection thread-safe est sûre, quoi que vous fassiez. Eh bien, ce n’était pas le cas et appeler une collection «thread-safe» lorsque l’opération la plus élémentaire d’une collection n’est pas thread-safe est bien sûr un problème. Ce que Microsoft voulait dire, c’était “il est sécurisé pour les threads, car l’utilisation de threads ne corrompra pas la collection”. Ce que les programmeurs ont lu était “c’est thread-safe”. Microsoft n’a pas répété la même erreur dans les classes de collection génériques .NET 2.0.

Cela a été résolu dans .NET 4, la répétition des nouvelles collections ne génère pas d’exception. Sinon, ils ne feront rien pour empêcher votre code de mal se comporter, car il lit des données obsolètes. C’est un problème insoluble que vous devez résoudre vous-même.

Le doublon lié répond à la partie “nouvelle fonctionnalité” de votre question. Je vais juste parler ici à cette note:

qu’est-ce qui a rendu impossible la réalisation de .NET 3.0

À mon avis, rien n’est impossible. Je suppose que si vous obtenez une décompilation des nouvelles classes dans .NET 4.0 et (avec des modifications de syntaxe si nécessaire), créez-les vous-même avec .NET 3.5, elles fonctionneraient parfaitement.

Ceci est identique à la façon dont, par exemple, Enumerable.Zip peut être implémenté manuellement dans .NET 3.5 , si .NET 4.0 n’est pas disponible. En effet, je me souviens d’avoir vu quelque part une implémentation de bibliothèques de type LINQ par rapport à .NET 2.0 (sans les fonctionnalités du langage C # bien sûr!).

En général, avec .NET, à moins que les bibliothèques ne dépendent de nouvelles fonctionnalités CLR , rien n’empêche la bibliothèque d’être réimplémentée par rapport à une version antérieure. Un exemple notable de la situation est celui des génériques: avant .NET 2.0, il n’existait aucun moyen d’obtenir un support de la collection typesafe sans gérer manuellement chaque classe, en utilisant peut-être des outils Codegen tels que CodeSmith .

Donc, si rien n’empêche l’existence des classes Concurrent dans .NET 3.5, pourquoi Microsoft ne les a-t-il pas créées alors? Simplement le temps et le budget – l’expédition est une fonctionnalité, et certaines fonctionnalités sont moins importantes que cela, elles doivent donc attendre une version ultérieure.