在C#实例方法中,'this'可以为null吗?

Der*_*ick 27 .net c# multithreading thread-safety

我有一种情况,很少有对象的队列出列空.对Enqueue的唯一调用是在类本身内:

m_DeltaQueue.Enqueue(this);
Run Code Online (Sandbox Code Playgroud)

很少,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);
    }
Run Code Online (Sandbox Code Playgroud)

这是生成的错误报告:

[Jan 23 01:53:13]:m_DeltaQueue.发生null的取消:m_DeltaQueue不为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>();
Run Code Online (Sandbox Code Playgroud)

排队:

    lock (_lock)
        m_DeltaQueue.Enqueue(this);
Run Code Online (Sandbox Code Playgroud)

出列:

       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();
Run Code Online (Sandbox Code Playgroud)

我仍然试图找到适当的同步,所以任何关于正确性的评论都将非常感激.我最初选择使用队列本身作为同步对象,因为它是私有的,并且对已经非常大的类引入了更少的混乱.基于John的建议,我将其更改为锁定一个新的私有静态对象_lock.

SLa*_*aks 30

this除非使用call手写IL中的指令调用该方法,否则永远不能为null .

但是,如果同时Queue在多个线程上使用相同的实例,则队列将损坏并丢失数据.

例如,如果将两个项目同时添加到近容量队列,则第二个项目可能会在第二个线程调整大小后将其添加到数组中,这将最终复制null到调整大小的数组并将第一个项目添加到旧的阵列.

您应该使用锁保护您的队列或使用.Net 4 ConcurrentQueue<T>.

  • 我猜它`ConcurrentQueue`甚至可能比手动锁定快一点,因为它可能使用无锁编程技术.您的使用应该使用`TryDequeue`方法. (6认同)
  • 使用ConcurrentQueue而不是锁定会导致性能下降吗?ConcurrentQueue似乎很简单.感谢有关如何实现这一目标的一个很好的例子. (2认同)
  • @CodeInChaos - 在许多情况下,无锁算法将执行涉及显式锁定的解决方案,但它不是给定的(任何人都可以找到一个好的参考?我用谷歌搜索但没找到一个).但是,使用经过良好测试的无锁解决方案几乎肯定比在非线程安全数据结构周围编码自己的锁定更不容易出错.直到它表明存在性能问题,在某种情况下,这种情况总是会引起我的选择. (2认同)