I have a situation where very rarely a Queue of Objects is dequeuing a null. The only call to Enqueue is within the class itself:
m_DeltaQueue.Enqueue(this);
Very rarely, a null is dequeued from this queue in the following code (a static method):
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);
}
This is the error report that was generated:
[Jan 23 01:53:13]:
m_DeltaQueue.Dequeue of a null
occurred: m_DeltaQueue is not null.
m_DeltaQueue.count:345
I'm very confused as to how a null value could be present in this queue.
As I'm writing this, I'm wondering if this could be a failure of thread synchronization; this is a multi threaded application and It's possible the enqueue or dequeue could be happening simultaneously in another thread.
This is currently under .Net 4.0, but it previously occurred in 3.5/2.0
Update:
This is my (hopefully correct) solution to the problem which was made clear though the great answers below as being a synchronization problem.
private static object _lock = new object();
private static Queue<Mobile> m_DeltaQueue = new Queue<Mobile>();
Enqueue:
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();
I'm still trying to get a handle on proper syncronization, so any comments on the correctness of this would be very appreciated. I initially chose to use the queue itself as a syncronization object because it's private, and introduces less clutter into what is already a very large class. Based on John's suggestion I changed this to lock on a new private static object, _lock.
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…