那麼我不是100%確定你試圖在這裏存檔。你是否試圖將所有物品出列,直到沒有剩下物品?或者只是一次將很多物品出列?
第一個可能的意外行爲啓動與此聲明:
theQueue.AsParallel()
對於ConcurrentQueue,你會得到一個「Snapshot'-枚舉。所以當你迭代一個併發堆棧時,你只能遍歷快照,不能訪問「實時」隊列。
總體而言,我認爲迭代迭代過程中改變的內容並不是一個好主意。
因此,另一種解決方案是這樣的:
// 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);
我會嘗試中間的想法,因爲這可能工作。這是一個Web服務的一部分,它可以在很短的時間內獲得10k次更新,每次只能處理1次,但我不想通過在獲取它們時嘗試每次更新來敲擊數據庫,所以我會將它們推入一個靜態隊列,一個單身,並有一個功能來處理。我的解決方案並不完美,但我需要將數據庫作爲高優先級來保護。 – 2010-06-11 00:48:24