Fixe la taille de la file d'attente qui retire automatiquement les anciennes valeurs sur les nouveaux enques
Je suis en utilisant ConcurrentQueue
pour une structure de données partagées, dont la finalité est maintenant le dernier N des objets passée (genre de l'histoire).
Supposons que nous avons un navigateur et nous voulons avoir le 100 derniers parcouru Url. Je veux une file d'attente qui automatiquement drop (file d'attente) la plus ancienne (la première) entrée sur nouvelle entrée d'insertion (mise en file d'attente) lorsque la capacité est pleine (100 adresses dans l'histoire).
Comment puis-je utiliser System.Collections
?
- stackoverflow.com/questions/590069/...
- Il n'était pas conçu spécifiquement pour vous, mais pour toute personne qui vient à travers cette question et pourrait trouver utile. btw, il ne parle de C# aussi. Avez-vous réussi à lire toutes les réponses (en 2 minutes) et la figure il n'existe pas de code C# il y a? De toute façon, je ne suis pas sûr moi-même, et par conséquent c'est un commentaire...
- Vous pouvez juste envelopper les méthodes dans une serrure. Étant donné qu'ils sont rapides, vous pouvez verrouiller l'ensemble du tableau. C'est probablement une dupe si la. La recherche de tampon circulaire mises en oeuvre avec le code C# pourrait vous trouver quelque chose. De toute façon, bonne chance.
Vous devez vous connecter pour publier un commentaire.
Je voudrais écrire une classe wrapper sur la mise en File d'attente serait de vérifier le Comte, puis file d'attente lorsque le nombre dépasse la limite.
q
est privé de l'objet, de sorte que lelock
va prévenir les autres threads d'accéder simultanément.Count
etTryDequeue
sont deux opérations indépendantes que les soins pas synchronisé par la BCL Simultanées.ConcurrentQueue<T>
objet d'unQueue<T>
objet qui est plus léger.ConcurrentQueue
et ajouternew
à laEnqueue
méthode?Enqueue
sera toujours appeler l'origine de la file d'attente. En d'autres termes, bien que cette réponse est marqué comme acceptée, c'est complètement et totalement brisé.ConcurrentQueue
mais la je ne peux pas remplacer laEnqueue
méthode.J'irais pour une variante légère... étendre ConcurrentQueue de manière à être capable d'utiliser les extensions Linq sur FixedSizeQueue
Pour toute personne qui estime utile, voici un peu de code de travail basé sur Richard Schneider réponse ci-dessus:
Pour ce que sa vaut la peine, voici un léger tampon circulaire avec certaines méthodes marqué pour la sécurité et l'utilisation non sécuritaire.
J'aime utiliser les
Foo()/SafeFoo()/UnsafeFoo()
convention:Foo
méthodes appelUnsafeFoo
en tant que par défaut.UnsafeFoo
méthodes de modifier l'état librement, sans une serrure, ne devrait en appeler d'autres utilisent des méthodes.SafeFoo
méthodes appelUnsafeFoo
méthodes à l'intérieur d'une serrure.C'est un peu verbeux, mais il fait des erreurs évidentes, comme d'appeler des méthodes dangereuses à l'extérieur d'un verrouillage dans une méthode qui est censé être thread-safe, de plus en plus apparente.
Voici mon point de vue sur le fixe de la taille de la File d'attente
Il utilise régulièrement la File d'attente, afin d'éviter la synchronisation de charge lorsque la
Count
propriété est utilisée surConcurrentQueue
. Il met également en œuvreIReadOnlyCollection
de sorte que LINQ méthodes peuvent être utilisées. Le reste est très similaire à d'autres réponses ici.Juste pour le fun, voici une autre mise en œuvre qui, je crois, traite de la plupart des commentateurs préoccupations. En particulier, le fil de sécurité est atteint sans verrouillage et la mise en œuvre est masqué par l'emballage de la classe.
_queue.Enqueue(obj)
mais avantInterlocked.Increment(ref _count)
, et l'autre thread appelle.Count
? Il serait d'obtenir un mauvais comptage. Je n'ai pas vérifié pour les autres questions.Ma version est juste une sous-classe de la normale
Queue
ceux.. rien de spécial mais en voyant tous les participants et il va encore avec le titre de la rubrique, je pourrais tout aussi bien le mettre ici. Il renvoie également le dequeued juste au cas où.Pour votre codage plaisir que je vous remets le '
ConcurrentDeck
'Exemple D'Utilisation:
Ajoutons une réponse de plus. Pourquoi ce au détriment des autres?
1) la Simplicité. Essayer de garantir la taille est bien, mais conduit à l'inutile complexité que peut présenter ses propres problèmes.
2) met en œuvre IReadOnlyCollection, ce qui signifie que vous pouvez utiliser Linq sur elle et la passer dans une variété de choses qui attendent IEnumerable.
3) Pas de verrouillage. Plusieurs des solutions ci-dessus utilisent des verrous, ce qui est incorrect sur un lockless collection.
4) met en œuvre les mêmes méthodes, les propriétés et les interfaces ConcurrentQueue, y compris IProducerConsumerCollection, ce qui est important si vous souhaitez utiliser la collection avec BlockingCollection.
Cette mise en œuvre pourrait potentiellement se retrouver avec plus d'entrées que prévu si TryDequeue échoue, mais la fréquence de celle qui se produit ne semble pas la peine de code spécialisé qui ne manqueront pas de gêner la performance et de la cause de ses propres problèmes inattendus.
Si vous voulez absolument garantir une taille, la mise en œuvre d'une Prune() ou une méthode similaire semble être la meilleure idée. Vous pouvez utiliser un ReaderWriterLockSlim verrou en lecture dans les autres méthodes (y compris TryDequeue) et de prendre un verrou en écriture uniquement lorsque la taille.
Bien, il dépend de l'utilisation, j'ai remarqué que certains de la solution ci-dessus peut dépasser la taille lorsqu'elle est utilisée dans de multiple ' -filetée de l'environnement. De toute façon mon cas d'utilisation a été pour afficher les 5 derniers événements et il y a plusieurs threads écrire des événements dans la file d'attente et un autre thread de lecture et de les afficher dans un Contrôle Winform. Donc c'était ma solution.
EDIT: étant donné que nous avons déjà à l'aide de verrouillage à l'intérieur de notre application nous n'avons pas vraiment besoin ConcurrentQueue il peut améliorer les performances.
EDIT: Nous n'avons pas vraiment besoin
syncObject
dans l'exemple ci-dessus, et nous pouvons utiliser plutôtqueue
objet dans la mesure où nous ne sommes pas ré-initialisation dequeue
dans n'importe quelle fonction et de ses marqués commereadonly
de toute façon.C'est ma version de la file d'attente:
Je trouve qu'il est utile d'avoir un constructeur qui est construit sur un IEnumerable et je trouve qu'il est utile d'avoir un GetSnapshot d'avoir un multi thread safe liste (array dans ce cas) des objets au moment de l'appel, qui ne remonte pas des erreurs si le sous-jacente de la collection de changements.
Le double Comptage vérification est pour éviter le blocage dans certaines circonstances.