그럼 여기에 보관하려는 내용을 100 % 확신하지 못했습니다. 아무것도 남지 않을 때까지 모든 항목을 큐에서 제거하려고합니까? 또는 한 번에 많은 항목을 큐에서 제거 할 수 있습니까?
첫 번째 아마 예기치 않은 동작이 문을 시작하십시오 ConcurrentQueue를 들어
theQueue.AsParallel()
, 당신은 '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 개 이상의 태스크를 생성하지 않습니다. 당신이 진짜 사이트 전반에 걸쳐 높은 목표로하고 즉시 DB 업데이트를 할 필요가없는 경우
// 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);
중간 아이디어를 시도해 볼 수 있습니다. 이것은 매우 짧은 시간에 한 번에 1 만 건의 업데이트를 얻을 수있는 웹 서비스의 일부이지만, 각 업데이트를 수행하면서 데이터베이스를 해머하고 싶지는 않습니다. 싱글 톤에 정적 대기열, 그리고 기능을 처리 할 수 있습니다. 내 솔루션이 완벽하지는 않지만 우선 데이터베이스를 보호해야합니다. –