J'ai remarqué que vous pouvez appeler Queue.Synchronize pour obtenir un objet de file d'attente thread-safe, mais la même méthode n'est pas disponible sur Queue <T>. Quelqu'un sait-il pourquoi? Cela semble un peu bizarre.
Réponses
Trop de publicités?Mise à jour - dans .NET 4, il est maintenant de ConcurrentQueue<T>
dans le Système.Les Collections.Simultanées, comme indiqué ici http://msdn.microsoft.com/en-us/library/dd267265.aspx. Il est intéressant de noter que son IsSynchronized méthode (à juste titre) renvoie la valeur false.
ConcurrentQueue<T>
est un terrain de réécriture, de la création de copies de la file d'attente à énumérer et à l'aide de advanced non-verrouillage des techniques comme l' Interlocked.CompareExchange()
et Thread.SpinWait()
.
Le reste de cette réponse est encore pertinent dans la mesure où il se rapporte à la disparition de l'ancien Synchronize() et SyncRoot membres, et pourquoi ils ne fonctionnent pas très bien à partir d'un point de vue API.
Comme par Zooba du commentaire, la BCL équipe a décidé que de trop nombreux développeurs ont été un malentendu le but de Synchroniser (et dans une moindre mesure, SyncRoot)
Brian Grunkemeyer décrit ce sur la BCL blog de l'équipe d'un couple d'années en arrière: http://blogs.msdn.com/bclteam/archive/2005/03/15/396399.aspx
La question clé est d'obtenir la bonne granularité autour de serrures, où certains développeurs auraient la naïveté de l'utilisation de plusieurs propriétés ou des méthodes sur un "synchronisé" de collecte et de croire que leur code soit thread-safe. Brian utilise File d'attente comme à son exemple,
if (queue.Count > 0) {
object obj = null;
try {
obj = queue.Dequeue();
Les développeurs ne se rendent pas compte que le Comte pouvait être changé par un autre thread avant de la file d'attente a été invoquée.
Forcer les développeurs à l'utilisation explicite de l'instruction lock autour de l'ensemble de l'opération d'éviter ce faux sentiment de sécurité.
Comme Brian mentionne, la suppression de SyncRoot a été en partie parce qu'il a été principalement mis en place pour appuyer Synchronisés, mais aussi parce que dans de nombreux cas, il y a un meilleur choix de la serrure de l'objet la plupart du temps, la File d'attente de l'instance elle-même, ou un
private static object lockObjForQueueOperations = new object();
sur la classe possédant l'exemple de la File d'attente...
Cette dernière approche est généralement plus sûre car elle permet d'éviter certaines autres communes de pièges:
Comme ils le disent, le filetage est dur, et ce qui semble simple peut être dangereux.
Vous pouvez trouver le CTP parallèle à vérifier; voici une entrée de blog des gars qui le mettent ensemble qui est assez d'actualité:
Énumération des collections simultanées
Ce n'est pas tout à fait la même chose, mais cela pourrait résoudre votre plus gros problème. (Ils utilisent même Queue<T>
contre ConcurrentQueue<T>
comme exemple.)
(Je suppose que vous voulez dire Queue<T> pour le second.)
Je ne peux pas vraiment répondre à la question, sauf que le IsSynchronized et SyncRoot propriétés (mais pas Synchroniser() explicitement) sont héritées de l'interface ICollection. Aucun des génériques des collections de l'utiliser et le ICollection<T> interface ne comprend pas SyncRoot.
Pourquoi il n'est pas inclus, je ne peux que spéculer qu'ils n'étaient pas utilisés, soit dans le sens voulu par les concepteurs de la bibliothèque ou tout simplement ils n'ont pas été suffisamment utilisés pour justifier leur maintien dans les collections récentes.