0

에 차단 그것은 모두에서 GetConsumingEnumerable() 스트림 및 일부 다른 기준에 (예 내에서 JobQueue) BlockingCollection<T> 블록 실행이 가능한가?<T> BlockingCollection .GetConsumingEnumerable()의 추가 조건

사용 가능한 슬롯이있을 때만 항목을 소비 할 수있는 상태 인 availableSlots > 0이 있습니다. 문제는 컬렉션에 항목이 있지만 조건이 거짓 일 때 foreach가 무기한 반복된다는 것입니다.

컬렉션을 availableSlots > 0에서도 차단하지 못합니까?

foreach (var job in JobQueue.GetConsumingEnumerable()) 
{ 
    if(availableSlots > 0) 
    { 
     JobHandler jobHandler = job; 

     Task.Factory.StartNew(() => 
     { 
      ExecuteJob(jobHandler); 
     }); 
    } 
} 

아마도이 모음을 잘못 사용하고 있습니다. 어떤 도움을 주셔서 감사합니다!

+0

'경우 (availableSlots> 0)'이게 ​​뭐야? 당신은 콜렉션 –

+0

에서 꺼낸 요소들을 무시하고 있습니다. 시나리오를 기반으로 루프 밖에서 상태 점검을 이동하는 것이 더 낫습니다. 필요없는 품목은 소비하지 마십시오. –

답변

2

값이 0 인 동안 차단하려는 경우 추가 동기화가 필요합니다. 그것은 정확하게 당신이 필요로 않기 때문에 나는 당신을위한 적합한 솔루션이 SemaphoreSlim 생각 : 대기 그 값이 그와 0

동안, 같이 보일 것입니다 코드 :

SemaphoreSlim slotsSemaphore = new SemaphoreSlim(…); 

… 

foreach (var job in JobQueue.GetConsumingEnumerable()) 
{ 
    slotsSemaphore.Wait(); 

    JobHandler jobHandler = job; 

    Task.Factory.StartNew(() => 
    { 
     try 
     { 
      ExecuteJob(jobHandler); 
     } 
     finally 
     { 
      slotsSemaphore.Release(); 
     } 
    }); 
} 
+0

이 접근법과 혼동을 느낍니다. 어떻게 작동합니까? 'initialCount'를'0'으로 설정하고'Wait()'를 호출하면 무한정으로 차단됩니까? 어떻게 풀어 줄거야? –

+0

'SemaphoreSlim'을 만들 때 보통 0이 아닌 값으로 설정합니다. 'Wait()'은 값을 감소시키고 (기다린 후에 즉시 처리 할 수없는 경우),'Release()'는 값을 증가시킵니다. – svick

+0

개수가 0 인 동안 차단을 위해 추가 동기화가 필요하지 않습니다.따라서 "BlockingCollection"이라는 이름 - 비어있을 때 Take(), TryTake() 및 GetConsumingEnumerable()에서 콜렉션이 차단됩니다. 이 클래스는 특별히 작성되었으므로 사용자가 직접 블로킹/신호 전송을 구현할 필요가 없습니다. –

0

이것이 최선의 방법인지는 모르겠지만 제 선택의 폭을 넓 힙니다.

사실 일 때까지 기다리지 않으시겠습니까?

while (availableSlots <= 0) 
{ 
    Thread.Sleep(1);//arbitary sleep 
} 

JobHandler jobHandler = job; 
... 

또는 사용 SpinWait

SpinWait.SpinUntil(() => availableSlots > 0); 

JobHandler jobHandler = job; 
... 

세 번째 옵션은 ManualResetEvent 또는 AutoResetEvent

signal.Waitone(); 

JobHandler jobHandler = job; 
... 

를 사용하고 availableSlots의 값을 변경할 때 signal을 설정하는 것입니다.

+2

바쁜 대기는 이에 대한 올바른 해결책이 아닙니다. – svick

+0

@svick 바쁜 말을하는 사람은 어느 것입니까? 둘 다 다른 스레드에 타임 슬라이스를 보냅니다. 바쁜 대기를 의미하는 것이 확실하지 않습니다. –

+0

답변 해 주셔서 감사합니다! Thread.Sleep() 접근법을 사용하려고 생각했지만 폴링에서 벗어나기를 희망했습니다. 어쩌면 나는'GetConsumingEnumerable()'을 경고하고 대신 콜렉션에서 수동으로'Take'와'TryTake'를 수동으로 해제해야합니까? – davenewza