BlockingCollection<T>.GetConsumingEnumerable () блокировка на дополнительное условие
Возможно ли иметь BlockingCollection<T>
(JobQueue
в моем примере) выполнение блока на обоих GetConsumingEnumerable()
стрим И по каким другим критериям?
У меня есть состояние availableSlots > 0
который позволяет использовать предметы только при наличии свободных слотов. Проблема в том, что foreach бесконечно зацикливается, когда в коллекции есть элементы, но условие ложно.
Могу ли я не получить коллекцию для блокировки availableSlots > 0
также?
foreach (var job in JobQueue.GetConsumingEnumerable())
{
if(availableSlots > 0)
{
JobHandler jobHandler = job;
Task.Factory.StartNew(() =>
{
ExecuteJob(jobHandler);
});
}
}
Возможно, я использую эту коллекцию неправильно. Любая помощь приветствуется!
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();
}
});
}
Не уверен, что это лучший способ, но выдвигаю мой вариант.
Почему бы просто не подождать, пока это не станет правдой?
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;
...
И установить signal
когда вы меняете значение availableSlots
,