是否可以在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);
});
}
}
也许我错误地使用了这个集合。任何帮助表示赞赏!
答案 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();
}
});
}
答案 1 :(得分: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;
...
更改signal
的值时设置availableSlots
。