我有一种情况,对象队列很少使空值出队。对 Enqueue 的唯一调用是在类本身中:
m_DeltaQueue.Enqueue(this);
在极少数情况下,在以下代码(静态方法)中 null 从该队列中出队:
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);
}
这是生成的错误报告:
[Jan 23 01:53:13]: m_DeltaQueue.Dequeue of a null occurred: m_DeltaQueue is not null. 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);
出队:
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();
我仍在尝试处理正确的同步,因此非常感谢任何对此正确性的评论。我最初选择使用队列本身作为一个同步对象,因为它是私有(private)的,并且在已经非常大的类中引入了更少的困惑。根据 John 的建议,我将其更改为锁定一个新的私有(private)静态对象 _lock。
最佳答案
this
永远不能为空,除非该方法是使用 call
调用的手写 IL 指令。
但是,如果您使用相同的 Queue
同时在多个线程上实例,队列将损坏并丢失数据。
例如,如果同时将两个项目添加到接近容量的队列中,则第一个项目可能会在第二个线程调整其大小后添加到数组中,这将最终复制一个 null
。到调整大小的数组并将第一项添加到旧数组。
您应该使用锁或使用 .Net 4 的 ConcurrentQueue<T>
来保护您的队列.
关于c# - 在 C# 实例方法中, 'this' 可以为空吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5055068/