В процессе разработки на платформе 1С:Предприятие 8 (особенно при работе с обычными формами в таких конфигурациях, как «Комплексная автоматизация 1.1» или «УПП 1.3») программисты часто сталкиваются с неочевидным поведением интерфейса. Одна из таких проблем — внезапное и ресурсозатратное обновление формы списка документов (например, Заказ покупателя) при выполнении простейших действий в дочернем окне, например, при установке галочки в списке привязанных файлов. Рассмотрим подробно причины этого поведения и способы оптимизации работы системы.
Первым делом проанализируем ситуацию, когда одна форма открывается из другой. В 1С существует понятие «Владелец формы». Когда мы открываем список файлов из формы документа, мы часто передаем владельца, чтобы дочерняя форма могла взаимодействовать с родительской. Рассмотрим типичный код открытия:
ФормаВыбора = Справочники.ХранилищеДополнительнойИнформации.ПолучитьФормуСписка();
ФормаВыбора.ВладелецФормы = ЭтаФорма; // Вот здесь устанавливается связь
ФормаВыбора.Открыть();
Как было замечено в ходе обсуждения проблемы, именно наличие этой связи часто становится триггером для обновления. В обычных формах платформа выстраивает иерархию событий. Если у формы есть владелец, любые действия, связанные с изменением или записью данных в подчиненной форме, могут инициировать проверку состояния формы-владельца и всех связанных с ней открытых окон. Если список документов является «предком» в этой цепочке, он получает сигнал о необходимости актуализации данных.
Разберем подробнее, почему платформа 1С считает нужным обновлять список документов, даже если мы напрямую этого не просили. В системе работает механизм неявного оповещения.
Когда в базе данных происходит изменение любого объекта (например, мы изменили реквизит справочника ХранилищеДополнительнойИнформации, установив галочку), платформа автоматически вызывает метод ОповеститьОбИзменении(). Все динамические списки (ДокументСписок, СправочникСписок), которые отображают данные этого типа или связаны с ним через критерии отбора или связи параметров выбора, «подписываются» на это событие автоматически.
В конфигурациях типа КА 1.1 список заказов часто содержит колонки, отображающие наличие файлов (иконка скрепки). Эта колонка работает через запрос к хранилищу данных. Следовательно, изменение в хранилище файлов дает сигнал списку документов: «Твои данные могли стать неактуальными, перечитай их».
Самый простой и действенный метод, который был найден опытным путем: отказаться от передачи владельца формы при открытии, если это не критично для логики работы. Если форме списка файлов не нужно напрямую обращаться к методам или элементам формы заказа, лучше открывать ее независимо.
Проанализируем разницу в подходе:
ОповеститьОбИзменении, но интенсивность этого процесса обычно ниже, так как нет прямой иерархической связи.Если нам все же необходимо оставить связь между формами, посмотрим на свойства элемента управления Табличное поле, которое отображает список заказов. У этого элемента есть важное свойство — ОбновлениеПриИзменении (RefreshOnChange).
Рассмотрим варианты настройки этого свойства:
Установка значения «Не обновлять» для табличного поля списка документов позволит избежать «подвисаний» интерфейса, когда пользователь работает с файлами. Однако помните, что в этом случае актуальные данные (например, статус заказа или наличие файлов) появятся в списке только после ручного обновления (кнопка F5 или кнопка «Обновить» на панели).
Часто в коде конфигурации (особенно самописной) присутствуют явные вызовы метода Оповестить(). Проанализируем типичный фрагмент кода в форме файлов:
Процедура ПриИзмененииГалочки(Элемент)
// Код записи данных
Если ВладелецФормы <> Неопределено Тогда
Оповестить("ОбновитьФорму", Новый Структура("ИмяЭлемента","ИзмененСписокФайлов"));
КонецЕсли;
КонецПроцедуры
В этом случае необходимо проверить форму списка заказов. Скорее всего, там в процедуре ОбработкаОповещения прописан код, который при получении события «ОбновитьФорму» выполняет метод ЭлементыФормы.СправочникСписок.Обновить().
Чтобы оптимизировать этот процесс, мы можем добавить условие, которое будет проверять, нужно ли действительно обновлять весь список или можно ограничиться обновлением только текущей строки:
Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
Если ИмяСобытия = "ОбновитьФорму" Тогда
// Вместо полного обновления списка:
// ЭлементыФормы.ДокументСписок.Обновить();
// Попробуем обновить только текущие данные, если это возможно
// Или игнорируем обновление, если форма списка в данный момент не активна
КонецЕсли;
КонецПроцедуры
Выясним причину, почему именно список документов «съедает» ресурсы. В обычных формах при обновлении динамического списка происходит следующее:
ПриВыводеСтроки или ПриПолученииДанных, они вызываются для каждой отображаемой записи.Если в ПриПолученииДанных (OnGetData) прописаны тяжелые запросы для определения наличия файлов или других статусов, то каждое «безобидное» нажатие галочки в маленьком окне файлов превращается в тяжелую операцию по пересчету всего основного списка заказов.
Рекомендация: Проверьте обработчик ПриПолученииДанных в форме списка заказов. Постарайтесь кэшировать результаты запросов или минимизировать количество обращений к базе данных внутри этого обработчика.
Подведем итог нашему разбору. Для устранения проблемы избыточного обновления формы списка документов при работе с файлами следует выполнить следующие шаги:
ВладелецФормы при открытии списка файлов. Если нет — убрать передачу владельца.ОбновлениеПриИзменении в значение Не обновлять, если мгновенная синхронизация списка документов с изменениями в файлах не требуется.Оповестить() и ОповеститьОбИзменении() в коде обработки «галочки».ПриПолученииДанных формы списка документов, чтобы минимизировать нагрузку при обновлении списка.Следуя этим шагам, мы добьемся плавной и быстрой работы интерфейса, не заставляя пользователей закрывать одни окна ради корректной работы других.