2015-12-18 20 views
5

Tôi gặp vấn đề với Nhà sản xuất/Người tiêu dùng. Hiện tại tôi đã đơn giản Queue được bao quanh bởi một lock.ConcurrentQueue cho phép tôi đợi một nhà sản xuất

Tôi đang cố gắng thay thế bằng thứ gì đó hiệu quả hơn.

Lựa chọn đầu tiên của tôi là sử dụng ConcurrentQueue, nhưng tôi không thấy làm thế nào để người tiêu dùng của tôi chờ tin nhắn được sản xuất tiếp theo (mà không cần làm Thread.Sleep).

Ngoài ra, tôi muốn có thể xóa toàn bộ hàng đợi nếu kích thước của nó đạt đến một số cụ thể.

Bạn có thể đề xuất một số lớp hoặc triển khai hiện có phù hợp với yêu cầu của tôi không?

+2

Bạn thử [ 'BlockingCollection'] (https://msdn.microsoft.com/en- chúng tôi/thư viện/dd267312% 28v = vs.110% 29.aspx) lớp học? –

+0

Hãy xem [câu hỏi này] (http://stackoverflow.com/questions/34255759/multiple-producers-single-consumer-locking-schema). Mặc dù nó là về nhiều nhà sản xuất, nó sẽ không quan trọng nếu bạn có một nhà sản xuất duy nhất. –

+0

Bạn có thể xây dựng trên _ "để xóa toàn bộ hàng đợi nếu kích thước của nó đạt được ..." _? Đối với các nhu cầu khác, BlockingCollection là lựa chọn lý tưởng. –

Trả lời

0

Dưới đây là một ví dụ về cách bạn có thể sử dụng lớp BlockingCollection để làm những gì bạn muốn:

BlockingCollection<int> blocking_collection = new BlockingCollection<int>(); 

//Create producer on a thread-pool thread 
Task.Run(() => 
{ 
    int number = 0; 

    while (true) 
    { 
     blocking_collection.Add(number++); 

     Thread.Sleep(100); //simulating that the producer produces ~10 items every second 
    } 
}); 

int max_size = 10; //Maximum items to have 

int items_to_skip = 0; 

//Consumer 
foreach (var item in blocking_collection.GetConsumingEnumerable()) 
{ 
    if (items_to_skip > 0) 
    { 
     items_to_skip--; //quickly skip items (to meet the clearing requirement) 
     continue; 
    } 

    //process item 
    Console.WriteLine(item); 

    Thread.Sleep(200); //simulating that the consumer can only process ~5 items per second 

    var collection_size = blocking_collection.Count; 

    if (collection_size > max_size) //If we reach maximum size, we flag that we want to skip items 
    { 
     items_to_skip = collection_size; 
    } 
} 
+0

Nice :) Trong lần thực hiện ban đầu của tôi, tôi đã thực hiện một 'while (blocking_collection.TryTake (out obj)) {}' (không phải là một vấn đề lớn nếu tôi bỏ lỡ thêm một phần tử nữa. Nhưng tôi cảm thấy việc triển khai của bạn nhanh hơn và chính xác hơn! việc thực hiện 'Peek', tôi sử dụng 'FirstOrDefault()', bạn nghĩ gì về nó? Tôi biết rằng nó không cản trở cái gì khác, nhưng trong trường hợp của tôi, nó không quan trọng – J4N

+1

Có thể giải thích tại sao bạn muốn Có lẽ có một cách tốt hơn để làm điều đó. –

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