BlockingCollection<T>
을 사용하여 생산자/소비자 패턴을 구현하려고하므로 간단한 콘솔 응용 프로그램을 작성하여 테스트 해 보았습니다.BlockingCollection.GetConsumingEnumerable을 올바르게 사용하는 방법?
내가 내 Main 메서드에서 대기/차단의 올바른 방법을 알고하지 않습니다
public class Program { public static void Main(string[] args) { var workQueue = new WorkQueue(); workQueue.StartProducingItems(); workQueue.StartProcessingItems(); while (true) { } } } public class WorkQueue { private BlockingCollection<int> _queue; private static Random _random = new Random(); public WorkQueue() { _queue = new BlockingCollection<int>(); // Prefill some items. for (int i = 0; i < 100; i++) { //_queue.Add(_random.Next()); } } public void StartProducingItems() { Task.Run(() => { _queue.Add(_random.Next()); // Should be adding items to the queue constantly, but instead adds one and then nothing else. }); } public void StartProcessingItems() { Task.Run(() => { foreach (var item in _queue.GetConsumingEnumerable()) { Console.WriteLine("Worker 1: " + item); } }); Task.Run(() => { foreach (var item in _queue.GetConsumingEnumerable()) { Console.WriteLine("Worker 2: " + item); } }); } }
그러나 내 디자인 3 문제가 있습니다. 간단한 빈 while 루프를 수행하는 것은 매우 비효율적이며 응용 프로그램이 종료되지 않도록 간단하게 낭비하는 CPU 사용량을 나타냅니다.
내 디자인에 또 다른 문제가 있습니다.이 간단한 응용 프로그램에서 아이템을 무기한 생산하며 절대 멈추지 말아야합니다. 실제 환경에서는 결국 파일을 종료해야합니다 (예 : 처리 할 파일이 부족한 경우). 이 경우 Main 메서드에서 완료 될 때까지 어떻게 기다려야합니까?
StartProducingItems
async
으로 작성한 다음await
으로 만드시겠습니까?GetConsumingEnumerable
또는Add
이 예상대로 작동하지 않습니다. 제작자는 끊임없이 항목을 추가해야하지만 한 항목을 추가 한 다음 더 이상 추가하지 않습니다. 이 한 항목은 소비자 중 한 명이 처리합니다. 두 소비자는 추가 될 품목을 기다리는 것을 차단하지만 아무 것도 없습니다.Take
방법을 알고 있지만 while 루프에서Take
을 다시 돌리면 꽤 낭비적이고 비효율적 인 것처럼 보입니다.CompleteAdding
메쏘드가 있습니다 만, 다른 어떤 것도 추가 할 수 없으며, 시도해도 예외가 발생하므로 적합하지 않습니다.
둘 다 소비자가 내가 디버깅하는 동안 스레드 사이를 전환 할 수 있습니다로, 차단하고 새 항목을 기다리고 사실에 있다는 것을 확실히 알고 :
편집 : 나는 '
의견 중 하나에서 변경 사항을 제안했지만 Task.WhenAll
은 여전히 즉시 반환됩니다.
public Task StartProcessingItems()
{
var consumers = new List<Task>();
for (int i = 0; i < 2; i++)
{
consumers.Add(Task.Run(() =>
{
foreach (var item in _queue.GetConsumingEnumerable())
{
Console.WriteLine($"Worker {i}: " + item);
}
}));
}
return Task.WhenAll(consumers.ToList());
}
'생산자는 지속적으로 항목을 추가해야하지만 항목을 하나 추가 한 다음 더 이상 추가하지 않습니다. 이 한 항목은 소비자 중 한 명이 처리합니다. 두 소비자는 추가 될 품목을 기다리는 것을 차단하지만 아무도는'그래, 네. 그 밖의 무엇을 기대 했습니까? 소비자가 항목이 추가 될 때까지 차단되므로 차단 컬렉션이라고합니다. –
아니요, 문제는 제작자가 항목을 하나 추가 한 다음 중지한다는 것입니다. – user9993
그것이 코딩 방법입니다. 단일 항목을 추가하는 작업을 시작합니다. 루프가 없습니까? –