На главную... Продукты | Технологии | Классификаторы | Проекты | Скачать | Цены| Форум | Статьи | Обучение | Контакты

Ошибка при закрытии слоя

Поиск  Пользователи  Правила  Войти
Форум » Настольные приложения » GIS ToolKit, GIS ToolKit Active, ГИС Конструктор для Windows
Страницы: 1 2 След.
RSS
Ошибка при закрытии слоя, Ошибка при закрытии слоя и освобождения select-ов
 

Добрый день, написал легенду карты, на подобии Вашей(конечно использовал SDK)))). Все работает хорошо, но при закрытии слоя и чиcтки select(освобождение памяти с FreeMemory() как в SDK) и , в дальнейшем, закрытии самого окна отображения(компонент MapScreen лежит на дочерней MDI форме, сообщение типа MT_CHANGEDATA посылаю) выскакивает сообщение об ошибке  в mapselt.pas, какие могут быть варианты, надо ли еще что-то посылать компоненту MapScreen? слой зарываю функцией mapCloseSiteForMap. GTK 11.14, dll 24/05/17 , c builder 6

Код
procedure TMapSelect.MapAction(aAction : TMapActionType);

... 

if (aAction = acBeforeClose) AND (FMV.MapHandle > 0)

  // Если закрыли карту

  then begin

  if FListSelect <> nil

    then begin

      for ii:=0 to FListSelect.Count-1

      do if FListSelect[ii] <> nil

         then begin

            mapDeleteSelectContext(HSelect(FListSelect[ii]));

            FListSelect[ii] := nil; // Здесь выдает сообщение

         end;

      FListSelect.Free;

      FListSelect := nil;

   end;

   if FListUses <> nil   then begin FListUses.Free; FListUses := nil; end;

   FListSelect:=TList.Create;

   FListSelect.Add(nil);

   FListUses:=TList.Create;

   FListUses.Add(Pointer(true));

   exit;

 end; // Если закрыли карту

Image 1.jpg (72.08 КБ)
 
Компоненты MapView и MapScreen самостоятельно не обрабатывают сообщение MT_CHANGEDATA, а лишь передают его далее всем подключенным к карте компонентам, которые в свою очередь обрабатывают это сообщение в соответствии со своей логикой.
Эта логика не всегда однозначна.

MapView и MapScreen при получении MT_CHANGEDATA могут только обновить габариты отображения карты в соответствии с новым составом данных.
Дело в том, что при работе с данными создаются цепочки классов TMapSite (TMapSites), TMapRst (TMapRsts) и другие.
Поскольку GIS ToolKit - это модульный инструментарий, просто взять и закрыть какой-то из этих классов при получении MT_CHANGEDATA нельзя, так как на нем могут быть завязаны другие компоненты либо пользовательский код. Тогда получим Access Violation уже в них.

Поэтому пока действует такое правило: открытая или добавленная карта самим компонентом MapView или MapScreen должна быть им же и закрыта.
В настоящее время не допускается смешение методов компонент и вызовов MAPAPI в части открытия и закрытия данных.
По Вашему коду я не увидел, как открывается карта, которую Вы закрываете с помощью mapCloseSiteForMap, но предположу, что открыта она методом компонента, а не MAPAPI-вызовом.
В результате, скорее всего, при закрытии формы компонент пытается освобождать все ресурсы, связанные с закрытой Вами картой, в том числе и описатели контекстов поиска и выделения (селекты), а они уже уничтожены внутри ГИС-ядра вызовом mapCloseSiteForMap.

Мы проанализируем еще раз обработку MT_CHANGEDATA и, возможно, расширим обработку.
Но я рекомендую в любом случае строить свой код по принципу "кто открыл, тот и закрыл", поскольку все вызовы напрямую в ГИС-ядро, минуя компоненты, впоследствии могут стать для компонент сюрпризом.
 
Цитата
Денис Вицко написал:
что открыта она методом компонента
Нет, карту открываю через mapOpenSiteForMapEx, после открытия, также, посылаю сообщение MT_CHANGEDATA компоненту MapScreen и всем своим задачам. Немного не понятно, почему нет проверки на количество данных(ситов, матриц и т.д.),если оно изменилось освободить память и заполнить заново, когда(на какое событие) заполняется список FListSelect и можно ли как-то проверить существует ли по данному адресу в памяти select?
Изменено: Максим Казаровец - 02.06.2017 13:55:28
 
Не совсем так. Классы цепочек данных TMapSites, TMapRsts и другие работают непосредственно с ГИС-ядром, то есть сами в курсе, какие данные сейчас открыты.
Проблема в тех классах, которые "цепляются" к ним и могут пытаться работать с данными по их номеру в цепочке (а он меняется при изменении состава), или, что серьезнее - по указателю (как в данном случае).  Со штатным списком Select-ов действительно должен разбираться GIS ToolKit самостоятельно.

Мы проверим корректность освобождения списка Select-ов.
Хотя, возможно, проблема не в закрытии карты (или не только в этом).
Можно взглянуть на код целиком?
Выслать можно на panorama@gisinfo.ru.

Цитата
Максим Казаровец написал:
можно ли как-то проверить существует ли по данному адресу в памяти select?
Для этого надо вести массив указателей на уровне ядра.
Для некоторых классов такие массивы ведутся, но это внутренняя кухня.
В настоящий момент - только следить за созданием и освобождением самостоятельно.
 
Цитата
Денис Вицко написал:
Можно взглянуть на код целиком?
Код по закрытию такой же как у Вас в SDK12\ready\mapclass. Если надо, то пришлю))) Проблема немного начала проясняться: есть открытая подложка, если добавляем первый слой и, потом, закрываем его, то ошибка не происходит. Если открываем первый слой и добавляем второй, затем, закрываем первый: вываливается приведенная ошибка, причем, второй закрывается не вызывая ошибку. Если открываем карту со слоями, т.е. создаем MDI окно с MapScreen, назначаем ему подложку и восстанавливаем данные, через mapRestoreMapState, и пытаемся закрыть слой через легенду получаем ошибку. После каждого изменения с данными посылаю соощение компоненту MT_CHANGEDATA.
Изменено: Максим Казаровец - 06.06.2017 11:46:21
 
Хочу обратить внимание на тот факт,  что для первой открытой карты создается документ с идентификатором hmap. Все добавляемые карты, добавляются к открытому документу и если его закрыть, то никакие другие карты и их идентификаторы больше не существуют. Таким образом, если необходимо закрыть только первую (основную) карту в документе, то необходимо закрыть все карты и открыть их заново кроме первой.
 
Цитата
Andrey Gheleznyakov написал:
и если его закрыть,
Первую(основную) карту никто не закрывает. Речь идет о закрытии пользовательских карт, добавленных к первой(основной). Ситуация такова, что при работе легенды карты создаются select-ы для объектов имеющихся на карте, всех объектов классификатора и т.д. При обновлении данных, закрытии легенды(деструктор формы легенды) чистятся только эти select-ы, но, каким-то образом, получается, что select-ы mapselt.pas тоже оказываются очищены! На какое событие это происходит пока не понятно. В Вашем случае, если основная карта была закрыта, то ошибки очистки select-ов должны происходить как и mapselt.pas, так и в моей легенде, при освобождении select-ов. Код по созданию и освобождению select-ов выслал Вам на ящик.
Изменено: Максим Казаровец - 07.06.2017 15:17:22
 
Проблема, скорее всего, в смешении вызовов функций MAP API и методов компонентов GTK. Для набора открытых карт, класс TMapSelect самостоятельно функциями MapApi создает набор hselect-ов, с которыми работают при селекции отображения и поиска в компонентах MapView, MapScreen. MapFind и других. Теперь вопрос: тот TMapSelect, который вызывает ошибку в каком компоненте используется? Есть подозрение, что дополнительные (не основные) карты вы закрываете напрямую вызывая функции MAP API. Дополнительные карты необходимо закрывать вызывая функции соответствующего компонента, например MapSreen.MapSites.Delete. Тогда будут корректно освобождаться созданные hselect в TMapSelect (иначе он будет в конце концов пытаться освободить повторно то, что уже освобождено при прямом вызове функции MAP API). Второй вариант для вас: самостоятельно создавать hselect для нужного hsite и тогда можно самостоятельно освобождать.
 
Код примера получили. Посмотрим.
 
Цитата
Andrey Gheleznyakov написал:
Теперь вопрос: тот TMapSelect, который вызывает ошибку в каком компоненте используется?
Добавление и закрытие слоев провожу через MapApi функции. HMAP беру из компонента TMapScreen, ничего, кроме MT_CHANGEDATA компоненту не присылаю, создаю свои select-ы и их же чищу. Заметил такую особенность: если закрыть слои mapapi функциями из других диалогов, где не используются select-ы, то ошибка не возникает. Вся разница, получается, в том, что в легенде я создаю свои select-ы и потом их чищу, а в других диалогах этого не делаю(не создаю и не чищу).
Страницы: 1 2 След.
Читают тему (гостей: 1)



© КБ Панорама, 1991-2024

Регистрируясь или авторизуясь на форуме, Вы соглашаетесь с Политикой конфиденциальности