У меня есть ситуация, когда очень редко Очередь Объектов вытесняет ноль. Единственный вызов Enqueue находится внутри самого класса:
m_DeltaQueue.Enqueue(this);
Очень редко нулевое значение удаляется из этой очереди в следующем коде (статический метод):
while (m_DeltaQueue.Count > 0 && index++ < count)
if ((m = m_DeltaQueue.Dequeue()) != null)
m.ProcessDelta();
else if (nullcount++ < 10)
{
Core.InvokeBroadcastEvent(AccessLevel.GameMaster, "A Rougue null exception was caught, m_DeltaQueue.Dequeue of a null occurred. Please inform an developer.");
Console.WriteLine("m_DeltaQueue.Dequeue of a null occurred: m_DeltaQueue is not null. m_DeltaQueue.count:{0}", m_DeltaQueue.Count);
}
Это отчет об ошибке, который был сгенерирован:
[23 января 01:53:13]:
m_DeltaQueue.Dequeue of null
произошло: m_DeltaQueue не является нулевым.
m_DeltaQueue.count: 345
Я очень озадачен тем, как нулевое значение может присутствовать в этой очереди.
Когда я пишу это, мне интересно, может ли это быть сбой синхронизации потоков; Это многопоточное приложение, и вполне возможно, что очередь или очередь могут происходить одновременно в другом потоке.
Это в настоящее время под .Net 4.0, но ранее это происходило в 3.5 / 2.0
Обновление:
Это моё (надеюсь правильное) решение проблемы, которое было прояснено, хотя приведенные ниже отличные ответы как проблема синхронизации.
private static object _lock = new object();
private static Queue<Mobile> m_DeltaQueue = new Queue<Mobile>();
Ставить:
lock (_lock)
m_DeltaQueue.Enqueue(this);
Dequeue:
int count = m_DeltaQueue.Count;
int index = 0;
if (m_DeltaQueue.Count > 0 && index < count)
lock (_lock)
while (m_DeltaQueue.Count > 0 && index++ < count)
m_DeltaQueue.Dequeue().ProcessDelta();
Я все еще пытаюсь разобраться с правильной синхронизацией, поэтому любые комментарии по поводу правильности этого будут очень благодарны. Первоначально я решил использовать саму очередь в качестве объекта синхронизации, потому что она частная и вносит меньше помех в то, что уже является очень большим классом. По предложению Джона я изменил это, чтобы заблокировать новый частный статический объект _lock.