【问题标题】:c# jagged array bug (elements are not always set)c# 锯齿状数组bug(元素并不总是设置)
【发布时间】:2012-08-16 21:58:31
【问题描述】:

我正在使用一个锯齿状数组来保存我正在制作的游戏中的地图片段(集群)。数组中的位置对应于集群在地图中的位置。此外,如果内部数组(锯齿状部分)不再加载任何集群(集群在未使用的超时后从数组中删除),则外部数组的元素设置回 null 以保持地图的内存使用下来。

当游戏试图从地图中获取集群时,问题似乎是随机出现的:

public Cluster getCluster(int xIndex, int yIndex)
{
    lock (xAxis)
    {
        loadCluster(xIndex, yIndex);
        return xAxis[xIndex][yIndex];
    }
}

public void loadCluster(int xIndex, int yIndex)
{
    lock (xAxis)
    {
        if (xAxis[xIndex] == null)
            xAxis[xIndex] = new Cluster[(int)worldSize.Y];
        if (xAxis[xIndex][yIndex] == null)
            xAxis[xIndex][yIndex] = new Cluster(this, new Vector2(xIndex * 256, yIndex * 256), worldLoader.loadClusterData(xIndex, yIndex));
    }
}

loadCluster(int, int) 方法应确保在 getCluster(int, int) 方法检索集群之前将其加载到数组中,并且几乎始终如此,但偶尔 loadCluster(int, int) 会以某种方式无法添加集群。

这似乎不会发生在任何特定的集群上,但总是在没有添加内部数组时发生(但是,大多数情况下它会毫无问题地创建内部数组)。 此外,当 Visual Studio 捕获随后的空指针异常时,退后一步并重新调用 loadCluster(int, int) 始终(至少到目前为止)正常工作。在getCluster(int, int) 方法中添加对loadCluster(int, int) 的额外调用也大大降低了此错误的频率。

老实说,我不知道是什么导致这个相当简单的功能不起作用,甚至看起来是随机的。任何帮助将不胜感激

编辑:编辑 xAxis[][] 的其他代码

public override void Update(GameTime gameTime)
{
    for (int x = 0; x < worldSize.X; x++)
    {
        if (xAxis[x] == null) continue;
        int loaded = 0;
        for (int y = 0; y < worldSize.Y; y++)
        {
            if (xAxis[x][y] == null)
            {
                continue;
            }
            xAxis[x][y].Update(gameTime);

            if (xAxis[x][y].clusterLoaded)
            {
                loaded++;
            }
            else if (xAxis[x][y].clusterTimer == 0)
            {
                xAxis[x][y] = null;
            }
        }

        if(loaded == 0) xAxis[x] = null;
    }
}

Cluster.clusterLoaded 是一个布尔值,显示集群当前是否正在使用。 Cluster.clusterTimer 是一个 int,一旦 clusterLoaded 变为 false,它就会倒计时。如果clusterLoaded 再次变为真,则将其重置为最大值。每次运行 Cluster.Update(GameTime)clusterLoaded 为 false 时,它​​会减 1。 loaded 用于统计当前内部数组加载了多少个Cluster。

【问题讨论】:

  • 没有代码确保 (int)worldSize.Y > yIndex。请添加这样的断言,以便在这种情况下中断。
  • 您能否发布所有更改数组的代码,包括从中删除的位 - 清理等?
  • 很好发现,但到目前为止代码的其他部分确保 yIndex 永远不会大于 worldSize.Y。尽管无论如何我都会添加签到。在任何情况下,即使 xIndex 和 yIndex 在数组的范围内,也会发生错误。

标签: c# multithreading nullpointerexception jagged-arrays


【解决方案1】:

这里要改变的第一件事是修改 loadCluster 方法以直接从中返回 xAxis[xIndex][yIndex] 值。这样就不需要锁定 getCluster 方法。 代码的其他部分呢?从描述来看,这似乎是一个多线程问题。尽管您已锁定 xAxis 变量,但我不知道您在其他地方还做了什么。 还有一点 - 语言中的数组确实是一项核心功能,所以那里有一个错误(我的意思是微软)真的是出乎意料的。

【讨论】:

  • loadCluster 只加载而不返回任何内容是故意的,我可能会将其设为私有/受保护。但是,您的多线程点很有趣。我有一个 BackgroundWorker,它会生成一个实时小地图,并且可能会产生干扰。我将对其进行一些测试。
  • 啊哈。它确实似乎是一个线程问题。停用 BackgroundWorker 可防止发生错误。我也设法找到了问题的根源。我没有在 Update 方法周围加锁,所以 BackgroundWorker 一定是把事情搞砸了。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-17
  • 1970-01-01
  • 2010-11-08
  • 2015-12-17
  • 1970-01-01
  • 2012-03-15
相关资源
最近更新 更多