Ошибка с зазубренным массивом в c # (элементы не всегда устанавливаются)

Я использую зубчатый массив для хранения сегментов карты (кластеров) в игре, которую я создаю. Положение в массиве соответствует положению кластера на карте. Кроме того, если внутренний массив (зубчатая часть) больше не имеет загруженных в него кластеров (кластеры удаляются из массива по истечении неиспользованного тайм-аута), этот элемент внешнего массива возвращается в нулевое значение, чтобы сохранить использование памяти картой. вниз.

Проблема возникает случайно, когда игра пытается получить кластер с карты:

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) всегда (по крайней мере, пока) работает как обычно. Добавление дополнительных вызовов loadCluster(int, int) в метод getCluster(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 - это целое число, которое ведет обратный отсчет, когда clusterLoaded становится ложным. Он сбрасывается, если на максимальное значение, если clusterLoaded снова становится истинным. Он уменьшается на 1 каждый раз, когда Cluster.Update(GameTime) выполняется, когда clusterLoaded ложно. loaded используется для подсчета количества загруженных кластеров в текущем внутреннем массиве.


person Kalia    schedule 16.08.2012    source источник
comment
Нет кода, гарантирующего, что (int) worldSize.Y ›yIndex. Пожалуйста, добавьте такое утверждение, чтобы в таком случае сломаться.   -  person Artak    schedule 17.08.2012
comment
Можете ли вы опубликовать весь код, который изменяет массив, включая удаляемые из него биты - очистку и т. Д.?   -  person Jeremy Rosenberg    schedule 17.08.2012
comment
Хорошо подмечено, но другие части кода пока гарантируют, что yIndex никогда не будет больше worldSize.Y. Хотя я все равно добавлю чек. В любом случае ошибка возникает, даже когда xIndex и yIndex находятся в пределах массива.   -  person Kalia    schedule 17.08.2012


Ответы (1)


Прежде всего, необходимо изменить метод loadCluster, чтобы он возвращал значение xAxis [xIndex] [yIndex] прямо из него. Тогда не нужно будет блокировать метод getCluster. Что насчет других разделов кода - из описания кажется, что это проблема с многопоточностью. Хотя вы заблокировали переменную xAxis, я не знаю, что еще вы делаете в другом месте. Еще один момент - массивы в языке действительно являются основной функциональностью, поэтому неожиданно иметь там ошибку (я имею в виду Microsoft).

person Artak    schedule 16.08.2012
comment
loadCluster только загрузка и ничего не возвращает намеренно, я, скорее всего, сделаю его закрытым / защищенным. Однако ваша многопоточность интересна. У меня есть BackgroundWorker, который генерирует живую миникарту и может мешать. Я буду тестировать его. - person Kalia; 17.08.2012
comment
Ага. Это действительно проблема с потоками. Деактивация BackgroundWorker предотвращает возникновение ошибки. Мне также удалось найти источник проблемы. Я не блокировал метод Update, так что BackgroundWorker, должно быть, все испортил. Большое спасибо! - person Kalia; 17.08.2012