Как устранить избыточное обновление динамических списков при изменении реквизитов формы в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с платформой 1С:Предприятие 8.3.20 (в частности, релиз 8.3.20.1613 и смежные) многие разработчики столкнулись с неприятной особенностью: динамические списки на управляемых формах начинают вести себя аномально. Проблема проявляется в том, что при изменении любого реквизита формы, даже если он никак не связан с данными списка, платформа инициирует повторное выполнение запроса динамического списка. Это происходит в тех случаях, когда в списке пользователем установлен какой-либо отбор.

Такое поведение приводит к заметным «фризам» интерфейса, особенно если запрос динамического списка сложный или база данных имеет внушительный объем. В крупных системах для оптимизации производительности может потребоваться многопоточная свёртка 1С:ERP для сокращения объема накопленных данных. В этой статье мы подробно разберем, почему это происходит, и рассмотрим эффективные методы борьбы с этой избыточностью.

Анализируем причину проблемы: механизм отслеживания зависимостей

Проанализируем ситуацию: в старых версиях платформы (до ветки 8.3.18) механизм обновления данных работал более избирательно. Начиная с версии 8.3.20, разработчики платформы внесли изменения в механизм отслеживания зависимостей данных на форме. Платформа стала считать, что любое изменение контекста формы потенциально может повлиять на результат запроса динамического списка, если в нем активны пользовательские настройки (отборы, группировки, условия).

Выясним причину, по которой это становится критичным именно при наличии отбора. Когда пользователь устанавливает фильтр, список переходит в состояние, требующее постоянной проверки актуальности отображаемых строк. Если в этот момент пользователь меняет значение простого числового или строкового реквизита на форме, платформа вызывает серверное событие ПриПолученииДанныхНаСервере, выполняя запрос к БД заново. В отладчике это легко отследить по факту попадания в указанный обработчик после каждого нажатия клавиши Enter в поле ввода.

Решение 1: Обновление или откат версии платформы

Это самый прямолинейный способ. Как показывает практика и опыт многих специалистов, данное поведение было признано ошибкой в реализации оптимизации платформы. Рассмотрим варианты:

  1. Откат на версию 8.3.18. В этой ветке механизм обновления списков работает корректно и не вызывает избыточных запросов при изменении несвязанных реквизитов.
  2. Обновление на актуальные релизы 8.3.22 или 8.3.23+. В более поздних сборках (например, начиная с 8.3.22.1709 и выше) 1С внедрила патчи, минимизирующие такие спонтанные обновления. Платформа вновь научилась более точно определять, влияют ли измененные данные формы на конкретный динамический список. При большом количестве информационных баз можно автоматизировать их архивирование и обновление по расписанию.

Решение 2: Программное управление отборами вместо пользовательских настроек

Разберем по шагам альтернативный метод, который позволяет обойти ошибку платформы, не меняя её версию. Проблема часто локализуется в «Пользовательских настройках» динамического списка. Если мы устанавливаем отбор не через стандартное окно настроек, а программно, платформа реже инициирует автоматическое обновление. Для детального изучения механизмов управления параметрами пригодится материал по работе с компоновщиком настроек динамического списка.

Рассмотрим пример кода, где мы устанавливаем отбор программно, делая его недоступным для случайного изменения механизмом автоматического отслеживания:


// Пример программной установки отбора в динамическом списке
&НаСервере
Процедура УстановитьЖесткийОтборНаСервере()
    
    // Очищаем существующие отборы, если это необходимо
    СписокЗаказов.КомпоновщикНастроек.Настройки.Отбор.Элементы.Очистить();
    
    // Создаем новый элемент отбора
    ЭлементОтбора = СписокЗаказов.КомпоновщикНастроек.Настройки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Номенклатура");
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
    ЭлементОтбора.Использование = Истина;
    ЭлементОтбора.ПравоеЗначение = Объект.ВыбраннаяНоменклатура;
    
    // Устанавливаем режим отображения "Недоступный", чтобы платформа не считала его
    // активной пользовательской настройкой, требующей постоянной сверки
    ЭлементОтбора.РежимОтображения = РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный;

КонецПроцедуры

Важно: использование свойства РежимОтображенияЭлементаНастройкиКомпоновкиДанных.Недоступный или БыстрыйДоступ часто помогает платформе исключить этот элемент из цепочки «жадного» обновления при изменении контекста формы.

Решение 3: Оптимизация интерфейса и разделение формы

Посмотрим на ситуацию с точки зрения эргономики и производительности UI. Платформа 1С оптимизирует отрисовку списков: если динамический список находится на неактивной вкладке (странице панели), запросы по нему обычно не выполняются до момента активации этой страницы.

Рассмотрим подробнее этот алгоритм:

  1. Разделим форму на несколько вкладок (группа страниц).
  2. Вынесем «тяжелый» динамический список (например, подбор номенклатуры) на отдельную вкладку.
  3. Реквизиты, которые часто меняются пользователем, оставим на основной вкладке.

В этом случае, пока пользователь работает с реквизитами на первой вкладке, список на второй вкладке не будет пересчитываться при каждом изменении данных, так как он не является видимым в текущий момент. Это значительно повышает отзывчивость интерфейса.

Решение 4: Использование свойства "Обновление при изменении данных"

Хотя в некоторых случаях это может не дать мгновенного эффекта (как отмечали пользователи в обсуждении), проанализируем свойство элемента формы ОбновлениеПриИзмененииДанных. У него есть три значения:

Попробуем установить это значение в Не обновлять для элемента таблицы. Однако помните, что в этом случае вам может потребоваться самостоятельно вызывать метод Элементы.СписокЗаказов.Обновить(), когда данные действительно изменятся и это будет необходимо пользователю.

Дополнительные рекомендации по работе с 8.3.20

Проанализируем еще один нюанс: использование произвольных запросов. Если ваш динамический список построен на произвольном запросе с параметрами, убедитесь, что параметры не привязаны напрямую к реквизитам формы через свойства связи. Лучше устанавливать параметры запроса явно в событии ПриИзменении конкретного реквизита:


&НаКлиенте
Процедура ЧисловойРеквизитПриИзменении(Элемент)
    // Простое изменение реквизита теперь не вызовет обновление списка,
    // так как мы убрали неявные связи в настройках списка
    РассчитатьСвязанныеПоказатели();
КонецПроцедуры

&НаСервере
Процедура ОбновитьПараметрыСписка()
    // Обновляем параметры только тогда, когда это действительно нужно
    СписокЗаказов.Параметры.УстановитьЗначениеПараметра("АктуальнаяДата", ТекущаяДата());
КонецПроцедуры

Подводя итог, можно сказать, что проблема избыточного обновления — это сложная комбинация поведения платформы и настроек конкретной формы. Комбинируя обновление платформы до стабильных веток с программным управлением отборами и оптимизацией размещения элементов на форме, вы сможете добиться плавной и быстрой работы интерфейса даже в сложных конфигурациях типа ERP или УТ 11.

← На главную