好吧,我不是 100% 确定您尝试在此处存档的内容。您是否试图将所有项目出列,直到什么都没有?或者只是一次出列大量项目?
第一个可能出乎意料的行为始于以下语句:
theQueue.AsParallel()
对于 ConcurrentQueue,您将获得一个“快照”枚举器。因此,当您迭代并发堆栈时,您只迭代快照,而不是“实时”队列。
一般来说,我认为迭代你在迭代过程中改变的东西不是一个好主意。
所以另一个解决方案看起来像这样:
// this way it's more clear, that we only deque for theQueue.Count items
// However after this, the queue is probably not empty
// or maybe the queue is also empty earlier
Parallel.For(0, theQueue.Count,
new ParallelOptions() {MaxDegreeOfParallelism = 20},
() => {
theQueue.TryDequeue(); //and stuff
});
这避免了在迭代某些东西时对其进行操作。但是,在该语句之后,队列仍然可以包含在 for 循环期间添加的数据。
要让队列暂时清空,您可能需要做更多的工作。这是一个非常丑陋的解决方案。当队列仍有项目时,创建新任务。只要可以,每个任务都开始从队列中出列。最后,我们等待所有任务结束。为了限制并行性,我们从不创建超过 20 个任务。
// Probably a kitty died because of this ugly code ;)
// However, this code tries to get the queue empty in a very aggressive way
Action consumeFromQueue = () =>
{
while (tt.TryDequeue())
{
; // do your stuff
}
};
var allRunningTasks = new Task[MaxParallism];
for(int i=0;i<MaxParallism && tt.Count>0;i++)
{
allRunningTasks[i] = Task.Factory.StartNew(consumeFromQueue);
}
Task.WaitAll(allRunningTasks);