在C#实例方法,可以'这'永远是空? [英] Within a C# instance method, can 'this' ever be null?

查看:117
本文介绍了在C#实例方法,可以'这'永远是空?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个情况很少的对象队列中出列空。入队的唯一调用类本身中:

  m_DeltaQueue.Enqueue(本);
 

极少数情况下,空从该队列在以下code(静态方法)离队

 而(m_DeltaQueue.Count> 0安培;&安培;指数++<计数)
    如果((M = m_DeltaQueue.Dequeue())!= NULL)
        m.ProcessDelta();
    否则如果(nullcount ++小于10)
    {
        Core.InvokeBroadcastEvent(AccessLevel.GameMaster,一个Rougue空异常被抓,一个空的m_DeltaQueue.Dequeue发生,请提前通知了开发商。);
        Console.WriteLine(空的m_DeltaQueue.Dequeue发生了:m_DeltaQueue不为空m_DeltaQueue.count:{0},m_DeltaQueue.Count);
    }
 

这是生成的错误报告:

  

[1月23日1点53分十三秒]:   一个空的m_DeltaQueue.Dequeue   发生:m_DeltaQueue不为空。   m_DeltaQueue.count:345

我很困惑,如何空值可能是present在此队列中。

正如我写这篇文章,我想知道这可能是线程同步的失败;这是一个多线程应用程序,并有可能入队或出队可以同时发生在另一个线程。

这是目前的.Net 4.0下,但它$ pviously发生P中$ 6.8 / 2.0

更新:

这是我(希望正确)的解决方案,这是明确不过下面的伟大的答案作为一个同步问题的问题。

 私有静态对象_lock =新的对象();
私有静态队列<移动> m_DeltaQueue =新问答LT;移动>();
 

排队:

 锁(_lock)
        m_DeltaQueue.Enqueue(本);
 

出列:

 诠释计数= m_DeltaQueue.Count;
       INT索引= 0;
       如果(m_DeltaQueue.Count> 0安培;&安培;指数<计数)
           锁(_lock)
               而(m_DeltaQueue.Count> 0安培;&安培;指数++<计数)
                   。m_DeltaQueue.Dequeue()ProcessDelta();
 

我还在试图让正确的同步化的手柄,所以在此正确性有任何意见将非常AP preciated。我最初选择使用队列本身作为一个同步化的对象,因为它是私有的,并引入了一些混乱到什么已经是一个非常大的类。根据约翰的建议,我改变了这种对一个新的专用静态对象锁定,_lock。

解决方案

不能为空,除非该方法是使用电话叫指令手写IL。

然而,如果你同时使用相同的队列实例上的多个线程,队列会损坏和数据丢失。

例如,如果两个项都同时加入到近容量队列中,第一项可能被添加到第二个线程调整大小后的数组,它最终将复制来调整大小的数组和添加的第一个项目,以旧数组。

您应该保护你的队列,锁或使用.NET 4中的 ConcurrentQueue< T>

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.

解决方案

this can never be null, unless the method was called using a call instruction in hand-written IL.

However, if you use the same Queue instance on multiple threads simultaneously, the queue will become corrupted and lose data.

For example, if two items are added simultaneously to a near-capacity queue, the first item might be added to the array after the second thread resizes it, which will end up copying a null to the resized array and adding the first item to the old array.

You should protect your queues with locks or use .Net 4's ConcurrentQueue<T>.

这篇关于在C#实例方法,可以'这'永远是空?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆