RUS  ENG 

Проблема получения структуры теплосети

Страницы: 1
RSS
Проблема получения структуры теплосети
 
Здравствуйте,

Пытаюсь получить структуру теплосети:

1. используя метод Layer.GetIncidentElements, но возникает сообщение о нехватке памяти
2. в цикле используя метод NetworkObjects.GetIncidentKeys, через какое-то время здесь возникает System.OutOfMemoryException, после возникновения ошибки, при закрытии соединения, соединение закрывается некорректно, из-за чего наступает блокировка по кол-ву подключений на IP-адрес.
Попытался еще добавить задержку между запросами (500 мс), но возникло другое исключение: HRESULT: 0x80010105 (RPC_E_SERVERFAULT)).

Как обойти проблему и получить всю структуру теплосети от Источника?

Язык программирования: C#
Версия ZuluServer: 8.0.0.7290u
Изменено: Быкиев Андрей - 28.04.2020 12:03:21
 
Цитата

1. используя метод Layer.GetIncidentElements , но возникает сообщение о нехватке памяти
2. в цикле используя метод NetworkObjects.GetIncidentKeys , через какое-то время здесь возникает System.OutOfMemoryException, после возникновения ошибки, при закрытии соединения, соединение закрывается некорректно, из-за чего наступает блокировка по кол-ву подключений на IP-адрес.

Как обойти проблему и получить всю структуру теплосети от Источника?

Язык программирования: C#
Версия ZuluServer: 8.0.0.7290u
Пришлите фрагмент кода, где метод используется.
А вообще, сеть получают через Layer.NetWorkObjects
 
Вот мой рекурсивный метод (с логикой обхода циклов):

Код
private static void GetChildren(int key, int prevKey, Layer layer)
        {
            int[] incidentKeys = layer.NetworkObjects[eNetworkObjectFilter.eNetworkAll].GetIncidentKeys(key, eIncidentRelationship.eIncidentAll).SaveToArray();

            for (int i = 0; i < incidentKeys.Length; i++)
            {
                if (incidentKeys[i] != prevKey)
                {
                    if (!items.Any(_ => _.Key == incidentKeys[i]))
                    {
                        items.Add(new TestModel()
                        {
                            Key = incidentKeys[i]
                        });
                    }

                    if (!items.Any(_ => _.Key == prevKey && _.Related != null && _.Related.Any(__ => __ == incidentKeys[i])))
                    {
                        var it = items.FirstOrDefault(_ => _.Key == prevKey);
                        if (it != null)
                        {
                            if (it.Related == null)
                                it.Related = new List<int>();

                            if (!it.Related.Any(_ => _ == incidentKeys[i]))
                                it.Related.Add(incidentKeys[i]);
                        }

                        //Thread.Sleep(500);
                        GetChildren(incidentKeys[i], key, layer);
                    }
                }
            }
        }

Класс TestModel:
Код
 public class TestModel
    {
        public int Key { get; set; }

        public List<int> Related { get; set; }
    }
items - коллекция типа TestModel
 
Цитата
Быкиев Андрей написал:
Вот мой рекурсивный метод (с логикой обхода циклов):

Код
 private static void GetChildren(int key, int prevKey, Layer layer)
        {
            int[] incidentKeys = layer.NetworkObjects[eNetworkObjectFilter.eNetworkAll].GetIncidentKeys(key, eIncidentRelationship.eIncidentAll).SaveToArray();

            for (int i = 0; i < incidentKeys.Length; i++)
            {
                GetChildren(incidentKeys[i], key, layer);                
            }
        } 

[CODE][/CODE]
Понятно. Вы рекурсивно по числу элементов сети создаете объект layer.NetworkObjects, который засасывает с сервера столько же раз всю сеть.
Это законно приводит к нехватке памяти. Если сеть большая, то быстро приведет.

GetIncidentKeys тоже рекурсивно создает коллекции, которые не высвобождаются и растут как снежный ком.

При определенной глубине сети и стека не хватит. не знаю возможности конкретно C##

Рекурсия вещь красивая, но опасная. Уходить вглубь нужно, не оставляя на каждом уровне объекты, занимающие память, размером с объем данных всего слоя или его части.
 
Алексей, спасибо, свою проблему понял, сейчас изменю логику. Остается пока вопрос - почему некорректно закрывается подключение при OutOfMemoryException именно при вызове этого метода через Layer.NetWorkObjects, метод Disconnect при этом не выдает никаких ошибок?
 
Цитата
Быкиев Андрей написал:
Алексей, спасибо, свою проблему понял, сейчас изменю логику. Остается пока вопрос - почему некорректно закрывается подключение при OutOfMemoryException именно при вызове этого метода через Layer.NetWorkObjects , метод Disconnect при этом не выдает никаких ошибок?
Да, еще. Объект NetworkObjects нужно получить с сервера один раз. Это и есть вся сеть. И дальше с ним работать.
Иначе есть риск, что при многопользовательском редактировании будете при разных обращениях к серверу за сетью, получать разные состояния сети
 
Спасибо, убрал из рекурсии запрос NetworkObjects и проблема решилась. Но все равно, вопрос с закрытием соединения при ошибке в Zulu остался открытым. Я перехватываю исключение в try/catch и в блоке finally всегда закрываю соединение.
 
Цитата
Быкиев Андрей написал:
Спасибо, убрал из рекурсии запрос NetworkObjects и проблема решилась. Но все равно, вопрос с закрытием соединения при ошибке в Zulu остался открытым. Я перехватываю исключение в try/catch и в блоке finally всегда закрываю соединение.
Тут нужно конкретно смотреть конкретный модуль. Соединение при аварийном завершении непредсказуемое дело. Если деструктор слоя, например, не вызвался, то и отсоединения не будет. Для этого штатно должны удалиться все объекты, связанные со слоем. И т.д. По идее сервер по таймеру должен, спустя время, соединение закрыть, если нет жизнедеятельности. Но тоже не всегда.
Чтобы исследовать, нужно воспроизвести ситуацию. Пришлите, если можно, модуль с ошибкой. Попробую воспроизвести
Страницы: 1