2012-05-24 15 views
6

Bir BlockingCollection içinde bir ConcurrentDictionary uygulamaya çalışıyorum ama başarılı görünmüyordu.BlockingCollection'da ConcurrentDictionary nasıl sarılır?

BlockingCollection<int> bag = new BlockingCollection<int>(new ConcurrentBag<int>()); 

:

ben böyle beyan ve örneğini olurdu bir değişken bildirimleri Yani, bir BlockingCollection sarılmış bir ConcurrentBag oluşturmak vb BlockingCollection gibi ConcurrentBag<T>, ConcurrentQueue<T> ile

çalışmak olduğunu anlamak ama ConcurrentDictionary için nasıl yapılır? Hem üretici hem de tüketici tarafında BlockingCollection'ın engelleme işlevine ihtiyacım var.

+0

Sözlük (ve ConcurrentDictionary da), öğelerin sırasını korumaz. Üretici-tüketici senaryosunu tarif edebilir misiniz? – Dennis

+0

@Dennis, Bunun farkındayım. Bir üretici, concurrentDictionary içinde KeyValuePairs depolar ve bir tüketici görevi bir int artar ve int, ilgili anahtarla eşleşiyorsa KeyValuePair'i kaldırır. Bunu yaparım çünkü çalışan görevleri concurrentDictionary değerini değerlerle doldurur, ancak rasgele sırayla, tüketici görevi alınan değerlerin doğru sırada çalışmasını/çalışmasını sağlar. ConcurrentDictionary bir BlockingCollection içinde sarılabilir mi? –

+0

Hangi çözümle geldiniz? Üreticinin tüketici tarafından ihtiyaç duyulan sırada ürün üretmediği benzer bir soruna iyi bir çözüm bulmaya çalışıyorum. (biliyorum eski mesaj, ama denemeye değer) – Kim

cevap

1

Kendi adaptör sınıf yazmak gerekir - gibi bir şey:

public class ConcurrentDictionaryWrapper<TKey,TValue> : IProducerConsumerCollection<KeyValuePair<TKey,TValue>> 
{ 
    private ConcurrentDictionary<TKey, TValue> dictionary; 

    public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() 
    { 
     return dictionary.GetEnumerator(); 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     return GetEnumerator(); 
    } 

    public void CopyTo(Array array, int index) 
    { 
     throw new NotImplementedException(); 
    } 

    public int Count 
    { 
     get { return dictionary.Count; } 
    } 

    public object SyncRoot 
    { 
     get { return this; } 
    } 

    public bool IsSynchronized 
    { 
     get { return true; } 
    } 

    public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index) 
    { 
     throw new NotImplementedException(); 
    } 

    public bool TryAdd(KeyValuePair<TKey, TValue> item) 
    { 
     return dictionary.TryAdd(item.Key, item.Value); 
    } 

    public bool TryTake(out KeyValuePair<TKey, TValue> item) 
    { 
     item = dictionary.FirstOrDefault(); 
     TValue value; 
     return dictionary.TryRemove(item.Key, out value); 
    } 

    public KeyValuePair<TKey, TValue>[] ToArray() 
    { 
     throw new NotImplementedException(); 
    } 
} 
+1

Kod önerisi için teşekkürler. Ama bir BlockingCollection kullanmadaki temel amacım, Toplama Tamamlandı olarak koleksiyonun işaretlenmesi ve durumunun kontrol edilmesi ve bunun bir BlockingCollection'ın sağladığı gibi, tam ve boş eklenmesi olup olmadığıdır. Bu işlevsellik kolayca ekleyebileceğimin farkındayım, ancak doğrudan BlockingCollection aracılığıyla nasıl yapılacağını gösteren bir öneri arıyorum. Şimdiye kadar, doğrudan Engelleme koleksiyonuyla çalışamamasının bir nedenini görmüyorum. Belki sadece IProducerConsumerCollection alır? –

4

Belki birşeyler bekliyor bu şekilde, bir tüketici tarafından blockingCollection

 ConcurrentDictionary<int, BlockingCollection<string>> mailBoxes = new ConcurrentDictionary<int, BlockingCollection<string>>(); 
     int maxBoxes = 5; 

     CancellationTokenSource cancelationTokenSource = new CancellationTokenSource(); 
     CancellationToken cancelationToken = cancelationTokenSource.Token; 

     Random rnd = new Random(); 
     // Producer 
     Task.Factory.StartNew(() => 
     { 
      while (true) 
      { 
       int index = rnd.Next(0, maxBoxes); 
       // put the letter in the mailbox 'index' 
       var box = mailBoxes.GetOrAdd(index, new BlockingCollection<string>()); 
       box.Add("some message " + index, cancelationToken); 
       Console.WriteLine("Produced a letter to put in box " + index); 

       // Wait simulating a heavy production item. 
       Thread.Sleep(1000); 
      } 
     }); 

     // Consumer 1 
     Task.Factory.StartNew(() => 
     { 
      while (true) 
      { 
       int index = rnd.Next(0, maxBoxes); 
       // get the letter in the mailbox 'index' 
       var box = mailBoxes.GetOrAdd(index, new BlockingCollection<string>()); 
       var message = box.Take(cancelationToken); 
       Console.WriteLine("Consumed 1: " + message); 

       // consume a item cost less than produce it: 
       Thread.Sleep(50); 
      } 
     }); 

     // Consumer 2 
     Task.Factory.StartNew(() => 
     { 
      while (true) 
      { 
       int index = rnd.Next(0, maxBoxes); 
       // get the letter in the mailbox 'index' 
       var box = mailBoxes.GetOrAdd(index, new BlockingCollection<string>()); 
       var message = box.Take(cancelationToken); 
       Console.WriteLine("Consumed 2: " + message); 

       // consume a item cost less than produce it: 
       Thread.Sleep(50); 
      } 
     }); 

     Console.ReadLine(); 
     cancelationTokenSource.Cancel(); 

bir eşzamanlı sözlüğe ihtiyacım 5. posta kutusunda 5, üreticinin posta kutusuna 5 yazmasını bekleyecektir.

İlgili konular