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