При разработке пользовательских интерфейсов в 1С разработчики часто сталкиваются с ситуацией, когда после открытия и последующего закрытия подчиненной или произвольной формы из кода формы-родителя удается беспрепятственно прочитать значения ее реквизитов. На первый взгляд это может показаться странным: почему после закрытия окна данные не уничтожаются?
Проанализируем ситуацию на примере следующего участка кода:
ФормаСерии = ПолучитьФорму("ФормаСерии");
ФормаСерии.ВладелецФормы = ЭтаФорма;
ФормаСерии.ОткрытьМодально();
// После закрытия окна ФормаСерии считываем реквизит:
ЗначениеСрока = ФормаСерии.СрокГодности;
Выясним причину такого поведения платформы 1С и разберем, как правильно работать с данными подчиненных форм.
Главный нюанс заключается в разделении графического отображения формы (окна пользовательского интерфейса) и программного объекта формы в оперативной памяти компьютера.
Рассмотрим подробнее, что происходит при вызове методов работы с формой:
ПолучитьФорму() платформа создает в памяти экземпляр объекта формы и возвращает ссылку на него в переменную (в нашем примере — ФормаСерии).ОткрытьМодально() или Открыть() отвечает исключительно за визуальное отображение созданной формы на экране и запуск пользовательского взаимодействия.Закрыть(), платформа убирает графическое окно с экрана и вызывает событие ПриЗакрытии.Однако сам программный объект формы не уничтожается мгновенно. Ссылка на объект формы продолжает храниться в локальной переменной ФормаСерии. Пока эта ссылка находится в области видимости выполняемой процедуры, реквизиты формы остаются полностью доступными для чтения и изменения из кода родительской формы.
Сохранение ссылок на закрытые формы в переменных — распространенная причина утечек памяти (Memory Leak) на стороне клиента. Объект формы продолжает удерживать свой контекст и занимать ресурсы оперативной памяти.
Посмотрим на пример правильного завершения работы с переменной формы при классическом подходе:
ФормаСерии = ПолучитьФорму("ФормаСерии");
ФормаСерии.ВладелецФормы = ЭтаФорма;
ФормаСерии.ОткрытьМодально();
// Получаем необходимые данные из формы
ЗначениеСрока = ФормаСерии.СрокГодности;
// Явно очищаем переменную для освобождения памяти
ФормаСерии = Неопределено;
Присвоение ФормаСерии = Неопределено; обнуляет последнюю ссылку на экземпляр формы, после чего сборщик мусора платформы 1С сможет окончательно удалить объект из оперативной памяти.
Использование методов ПолучитьФорму() и ОткрытьМодально() считается устаревшей практикой. В современных конфигурациях (управляемое приложение, веб-клиент, режим запрета модальных окон) считывание данных напрямую из объекта закрытой формы не рекомендуется или является технически невозможным из-за асинхронности работы вызовов.
Разберем по шагам безопасные и стандартные механизмы передачи данных из дочерней формы в форму-владелец:
ОповеститьОВыборе)
В дочерней форме при выполнении целевого действия вызывают метод передачи данных владельцу:
// В коде подчиненной формы
СтруктураРезультата = Новый Структура;
СтруктураРезультата.Вставить("СрокГодности", ЭтотОбъект.СрокГодности);
ОповеститьОВыборе(СтруктураРезультата);
Форма-владелец принимает эти данные в своем стандартном клиентском обработчике ОбработкаВыбора(РезультатВыбора, ИсточникВыбора).
ОписаниеОповещения
При открытии дочерней формы через ОткрытьФорму() передается специальное описание оповещения о закрытии:
// В форме-владельце
ОписаниеОповещения = Новый ОписаниеОповещения("ПослеЗакрытияФормыСерии", ЭтаФорма);
ОткрытьФорму("Документ.ПоступлениеТоваров.Форма.ФормаСерии", , ЭтаФорма, , , , ОписаниеОповещения);
// Процедура-обработчик результатов закрытия
&НаКлиенте
Процедура ПослеЗакрытияФормыСерии(РезультатЗакрытия, ДополнительныеПараметры) Экспорт
Если РезультатЗакрытия <> Неопределено Тогда
// Работаем с полученными данными
СрокГодности = РезультатЗакрытия.СрокГодности;
КонецЕсли;
КонецПроцедуры
В самой дочерней форме закрытие выполняется с передачей структуры данных: Закрыть(СтруктураРезультата);.
Если из формы нужно передать большой объем данных или сложную структуру, подчиненная форма помещает данные во временное хранилище на сервере, используя УникальныйИдентификатор формы-владельца. Владелец считывает данные из хранилища по адресу после получения уведомления о закрытии.
Таким образом, помните: визуальное закрытие окна в 1С лишь скрывает его от пользователя. Чтобы гарантировать корректную работу приложения и избежать утечек памяти, всегда используйте штатные асинхронные механизмы передачи данных через ОписаниеОповещения или ОповеститьОВыборе.