Création d'une File d'attente de blocage<T> dans .NET?

J'ai un scénario où j'ai plusieurs threads ajout d'une file d'attente et plusieurs threads de lecture à partir de la même file d'attente. Si la file d'attente atteint une taille spécifique tous les threads qui sont le remplissage de la file d'attente sera bloqué sur ajouter jusqu'à un point est retiré de la file d'attente.

La solution ci-dessous est ce que je suis en ce moment et ma question est: Comment cela peut-il être amélioré? Est-ce un objet qui permet déjà ce comportement dans la BCL que je devrais utiliser?

internal class BlockingCollection<T> : CollectionBase, IEnumerable
{
//todo: might be worth changing this into a proper QUEUE
private AutoResetEvent _FullEvent = new AutoResetEvent(false);
internal T this[int i]
{
get { return (T) List[i]; }
}
private int _MaxSize;
internal int MaxSize
{
get { return _MaxSize; }
set
{
_MaxSize = value;
checkSize();
}
}
internal BlockingCollection(int maxSize)
{
MaxSize = maxSize;
}
internal void Add(T item)
{
Trace.WriteLine(string.Format("BlockingCollection add waiting: {0}", Thread.CurrentThread.ManagedThreadId));
_FullEvent.WaitOne();
List.Add(item);
Trace.WriteLine(string.Format("BlockingCollection item added: {0}", Thread.CurrentThread.ManagedThreadId));
checkSize();
}
internal void Remove(T item)
{
lock (List)
{
List.Remove(item);
}
Trace.WriteLine(string.Format("BlockingCollection item removed: {0}", Thread.CurrentThread.ManagedThreadId));
}
protected override void OnRemoveComplete(int index, object value)
{
checkSize();
base.OnRemoveComplete(index, value);
}
internal new IEnumerator GetEnumerator()
{
return List.GetEnumerator();
}
private void checkSize()
{
if (Count < MaxSize)
{
Trace.WriteLine(string.Format("BlockingCollection FullEvent set: {0}", Thread.CurrentThread.ManagedThreadId));
_FullEvent.Set();
}
else
{
Trace.WriteLine(string.Format("BlockingCollection FullEvent reset: {0}", Thread.CurrentThread.ManagedThreadId));
_FullEvent.Reset();
}
}
}
  • .Net comment construit-dans les classes pour aider à ce scénario. La plupart des réponses énumérées ici sont obsolètes. Voir les plus récentes réponses au bas. Regardez dans les thread-safe blocage des collections. Les réponses peuvent être obsolètes, mais c'est toujours une bonne question!
  • Je pense que c'est toujours une bonne idée d'apprendre sur le Moniteur.Wait/Impulsion/PulseAll même si nous avons des nouvelles concurrentes des classes dans .NET.
  • D'accord avec @thewpfguy. Vous aurez envie de comprendre la base des mécanismes de verrouillage de derrière les coulisses. Également intéressant de noter que les Systèmes.Les Collections.Simultanées n'existait pas jusqu'en avril 2010, et alors seulement dans Visual Studio 2010 et au-dessus. Définitivement pas une option pour le VS2008 tenir les aboutissants...
  • Si vous lisez ceci maintenant, jetez un oeil au Système.Le filetage.Les canaux multi-écrivain/multi-lecteur, borné, éventuellement le blocage de la mise en œuvre de ce pour .NET de Base et .NET Standard.