2012-04-15 6 views
0

nが順序付きキーで定義されているn番目の要素で、キューが必要です。ConcurrentQueueのメソッドで再キューが必要です。>

ConcurrentQueue<KeyValuePair<string, SomeClass>> queue = new ConcurrentQueue<KeyValuePair<string, SomeClass>>(); 


queue.RequeueByOrderedKey(key, element) 

OR

queue.RequeueN(index, element) 

...それは、私が公共

class Class1 : KeyedCollection<K,V>{} 

    it'd be nice to have Class1 : OrderedKeyedCollection<K,V>{} 

に基づいて何かを検討している自分自身をこれを実装するために必要になりますので、ここで私がやったいくつかのコードです。私はコメントのためにここに置いて、それをおそらく答えに移します。たぶん、並行処理はまだ適切に処理されていないでしょう。

public class QueueExt<TK, TV> : SortedList<TK, TV> { 

     #region Constructors 

     public QueueExt(Func<TV, TK> getKey = null) { 
      GetKey = getKey; 
     } 

     private Func<TV, TK> GetKey = null; 

     public QueueExt(int capacity, Func<TV, TK> getKey = null) 
      : base(capacity) { 
      GetKey = getKey; 
     } 

     public QueueExt(IComparer<TK> comparer, Func<TV, TK> getKey = null) 
      : base(comparer) { 
      GetKey = getKey; 
     } 

     public QueueExt(int capacity, IComparer<TK> comparer, Func<TV, TK> getKey = null) 
      : base(capacity, comparer) { 
      GetKey = getKey; 
     } 

     public QueueExt(IDictionary<TK, TV> dictionary, Func<TV, TK> getKey = null) 
      : base(dictionary) { 
      GetKey = getKey; 
     } 

     public QueueExt(IDictionary<TK, TV> dictionary, IComparer<TK> comparer, Func<TV, TK> getKey = null) 
      : base(dictionary, comparer) { 
      GetKey = getKey; 
     } 

     #endregion 

     public TV Dequeue() { 
      lock (this) { 
       var first = this.ElementAt(0).Value; 
       this.RemoveAt(0); 
       return first; 
      } 
     } 

     public void Requeue() { 

      if (GetKey == null) 
       throw new ArgumentNullException("Key getter lamda must not be null"); 

      lock (this) { 
       var key = this.ElementAt(0).Key; 
       var actualkey = GetKey(this.ElementAt(0).Value); 
       if (!actualkey.Equals(key)) { 
        this.Enqueue(this.Dequeue()); 
       } 
      } 
     } 

     public void Enqueue(TK key, TV item) { 
      this.Add(key, item); 
     } 
     public void Enqueue(TV item) { 
      if (GetKey == null) 
       throw new ArgumentNullException("Key getter lamda must not be null"); 
      var key = GetKey(item); 
      this.Add(key, item); 
     } 

     public TV Peek() { 
      return this.ElementAt(0).Value; 
     } 
    } 

答えて

1

BlockingCollectionでこれを行うことができます。インデックス可能なキューを作成し、IProducerConsumerCollectionを実装するようにします。私はどのようにBlockingCollection私の記事でこの方法を使用する方法を示しています。記事でスタックを使用していますが、スタックをインデックス可能なキューに簡単に置き換えることは簡単です。

これに代わるものとして、並行優先度キューがあります。ヒープとロックでシンプルなものを作ることができます。私の記事A Generic Binary Heapを参照してください。同期を追加する必要があります。

+0

基礎となるコレクションは同時に存在する必要がありますか? IProducerConsumerCollectionはIEnumerable 、ICollection、IEnumerableを実装します。先端に感謝します。私はそれが持っている名前を考えて私がこれを調べたことさえ確信していません。それはちょうど関連性があるとは言えませんでしたが、それが意味することを考えれば理にかなっています。どうやってそれを見つけましたか? – sgtz

+0

複数のスレッドから使​​用する場合は、基になるコレクションが同時に存在する必要があります。もちろん、ロックを使用して並行性を実装することもできます。私はBlockingCollectionを探していたので、キューに入れることができるものの数を制限することができました。 –

+0

は私が好きなもので基本的な辞書をキーすることができるようです - そのため、根底から取り除き、再度ブロックすることができます。これについてテストしようとしています。 – sgtz

1

いいえ、それはそれはqueueのエッセンスだ原因、あなたはそれにキーまたはインデックスのアクセス権を持つことができない、ことはできませんよ。これにはList<>を使用してください。

+0

私はある種のハイブリッドを探しています。明らかに、キューモデルはこれを可能にする可能性があります。私がナイトクラブに入るためにキューイングしていると、女性はキューを完全にジャンプすることができます(つまり、バウンサーと話す、またはVIPステータスを務める)、またはすでにキューイングしている友達に参加できます。本質はあなたがそれを定義するものです。 – sgtz

+0

@downvoter:説明する気に? – Tigran

+0

@sgtz:インデックスアクセスやオーダーのために*設計されていない*キューを繰り返します。それは構造の異なるタイプです。あなたはいくつかのFIFO構造を必要としますが、索引*および* ordedアクセス(ポスト上でのlloking)を必要とします。したがって、リストの単純な実装を使用することはまさに必要なものです。 – Tigran

関連する問題