Вы говорите:
несколько потоков помещают данные в очередь
Метод Queue<T>.Enqueue
не является потокобезопасным. Это означает, что работа выполняется в методе Enqueue
, который необходимо синхронизировать, если его вызывают несколько потоков. Простым примером будет обновление свойства Count
. Можно с уверенностью сказать, что где-то в методе Enqueue
есть строка, которая выглядит примерно так:
++count;
Но, как мы все знаем, это не атомарная операция. Это действительно больше похоже на это (с точки зрения того, что на самом деле происходит ):
int newCount = count + 1;
count = newCount;
Так, скажем, count
в настоящее время 5, а поток 1 проходит int newCount = count + 1
... тогда поток 1 думает: «Хорошо, счетчик теперь 5, поэтому я сделаю его 6». Но самая следующая выполняемая операция - это когда поток 2 добирается до int newCount = count + 1
и думает так же, как поток 1 («теперь счетчик равен 6»). Таким образом, два элемента были добавлены в очередь, но их количество изменилось с 5 до 6.
Это просто очень простой пример того, как не потокобезопасный метод, такой как Queue<T>.Enqueue
, может быть испорчен, когда доступ не синхронизирован. Это конкретно не объясняет, что происходит в вашем вопросе; я хочу просто указать, что то, что вы делаете, не является поточно-ориентированным и приведет к неожиданному поведению .