2012-05-24 14 views
6

Tôi cố gắng triển khai ConcurrentDictionary bằng cách gói nó trong một BlockingCollection nhưng dường như không thành công.Làm thế nào để bọc ConcurrentDictionary trong BlockingCollection?

Tôi hiểu rằng một khai báo biến làm việc với BlockingCollection như ConcurrentBag<T>, ConcurrentQueue<T> vv

Vì vậy, để tạo ra một ConcurrentBag bọc trong một BlockingCollection tôi sẽ kê khai và nhanh chóng như thế này:

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

nhưng làm thế nào để làm điều đó cho ConcurrentDictionary? Tôi cần chức năng chặn của BlockingCollection ở cả phía nhà sản xuất và người tiêu dùng.

+0

Từ điển (và ConcurrentDictionary nữa) không giữ thứ tự các mục. Bạn có thể mô tả kịch bản người tiêu dùng sản xuất của bạn không? – Dennis

+0

@ Dennis, tôi biết điều đó. Một nhà sản xuất lưu trữ KeyValuePairs trong concurrentDictionary, và một nhiệm vụ tiêu dùng tăng một int và loại bỏ KeyValuePair nếu int khớp với khóa tương ứng. Tôi làm điều này bởi vì các nhiệm vụ của nhân viên cư trú concurrentDictionary với các giá trị nhưng theo thứ tự tùy ý, nhiệm vụ của người tiêu dùng đảm bảo các giá trị nhận được được truyền vào/làm việc theo thứ tự đúng. ConcurrentDictionary có thể được bao bọc trong BlockingCollection không? –

+0

Bạn đã đưa ra giải pháp nào? Tôi đang cố gắng tìm một giải pháp tốt cho một vấn đề tương tự, nơi nhà sản xuất không sản xuất các mặt hàng theo thứ tự mà người tiêu dùng cần. (bài cũ tôi biết, nhưng nó đáng để thử) – Kim

Trả lời

1

Bạn sẽ cần phải viết lớp bộ chuyển đổi của riêng bạn - một cái gì đó như:

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

Cảm ơn bạn đã gợi ý mã. Nhưng mục đích chính của tôi trong việc sử dụng BlockingCollection là khả năng đánh dấu bộ sưu tập là Thêm Đã hoàn thành và để kiểm tra trạng thái của nó cũng như việc nó thêm hoàn chỉnh và trống, tương tự như những gì một BlockingCollection cung cấp. Tôi biết tôi có thể dễ dàng thêm chức năng như vậy, nhưng tôi đang tìm kiếm một gợi ý làm thế nào để làm điều đó trực tiếp thông qua BlockingCollection. Cho đến nay tôi không thấy lý do tại sao nó không thể làm việc trực tiếp thông qua bộ sưu tập Chặn. Có lẽ nó chỉ mất IProducerConsumerCollection ? –

4

Có lẽ bạn cần một cuốn từ điển đồng thời 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(); 

Bằng cách này, một người tiêu dùng được mong đợi một cái gì đó trong hộp thư 5, sẽ đợi cho đến khi nhà sản xuất đặt một chữ cái trong hộp thư 5.

Các vấn đề liên quan