В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда стандартная операция установки отбора в динамическом списке приводит к длительному зависанию интерфейса. Казалось бы, простая строка кода, присваивающая значение элементу отбора, не должна вызывать таких последствий. Однако механизм работы управляемых форм гораздо сложнее, чем кажется на первый взгляд. Разберем детально, почему это происходит и как правильно реализовать поиск, чтобы избежать блокировок.
Рассмотрим фрагмент кода, в котором происходит зависание. В данном примере разработчик пытается программно установить отбор в динамическом списке Товары, используя КомпоновщикНастроек:
ЭлементОтбора = Товары.КомпоновщикНастроек.Настройки.Отбор.ПолучитьОбъектПоИдентификатору(СтруктураВидовПоискаИЭлементовОтбора[ВидПоиска]);
// Вот здесь и происходит зависание
Если ЭлементОтбора <> Неопределено Тогда
ЭлементОтбора.Использование = Истина;
ЭлементОтбора.ПравоеЗначение = ПолеПоиска;
ПоискССозданиемСписков = Ложь;
КонецЕсли;
Зависание на строке ЭлементОтбора.ПравоеЗначение = ПолеПоиска — это классический симптом, указывающий на то, что платформа в этот момент инициирует ряд фоновых процессов. Хотя мы просто присваиваем значение переменной, внутри системы запускается механизм синхронизации и валидации данных.
Когда мы изменяем коллекцию КомпоновщикНастроек.Настройки, платформа автоматически пытается синхронизировать эти изменения с объектом ПользовательскиеНастройки. Если динамический список имеет сложную структуру, множество предопределенных отборов или иерархические группы (И, ИЛИ, НЕ), процесс пересчета визуального состояния формы может занять значительное время. Платформа анализирует, должен ли этот отбор отобразиться в пользовательском окне настроек, и обновляет дерево элементов в памяти, что вызывает задержку в основном потоке интерфейса.
Динамический список в 1С спроектирован так, чтобы данные подгружались порциями. Однако установка нового значения в ПравоеЗначение часто интерпретируется системой как сигнал к немедленному перестроению кэша данных. Проанализируем, что происходит в этот момент:
Интерфейс «замирает», так как управляемая форма ожидает ответа от сервера приложений о том, что отбор принят и данные могут быть отображены.
Если ПолеПоиска связано с реквизитом, по которому в SQL-базе не построен индекс, любая попытка фильтрации приведет к полному сканированию таблицы (Full Scan). В случае с динамическим списком товаров, где записей могут быть сотни тысяч, установка значения отбора заставляет сервер базы данных «перелопачивать» весь объем данных. Пока СУБД не вернет первые результаты, выполнение кода 1С на строке присвоения будет приостановлено.
Чтобы избежать подобных зависаний, мы можем воспользоваться несколькими альтернативными подходами, которые работают более эффективно.
Вместо того чтобы изменять основные настройки, попробуем обратиться напрямую к пользовательским настройкам компоновщика. Это более «легкий» способ взаимодействия с интерфейсом:
Для Каждого Элемент Из Товары.КомпоновщикНастроек.ПользовательскиеНастройки.Элементы Цикл
Если ТипЗнч(Элемент) = Тип("ЭлементОтбораКомпоновкиДанных")
И Элемент.ИдентификаторПользовательскойНастройки = НужныйИдентификатор Тогда
Элемент.Использование = Истина;
Элемент.ПравоеЗначение = ПолеПоиска;
Прервать;
КонецЕсли;
КонецЦикла;
Работа с ПользовательскиеНастройки позволяет избежать некоторых этапов внутренней синхронизации метаданных, которые происходят при прямой модификации Настройки.Отбор.
Если поиск осуществляется по конкретному полю (например, Артикул или Штрихкод), мы рекомендуем изменить текст запроса динамического списка, добавив туда параметры. Выясним, почему это быстрее: параметры данных обрабатываются платформой на уровне формирования SQL-запроса более оптимально, чем динамические коллекции отборов.
Пример установки параметра:
ПараметрПоиска = Товары.КомпоновщикНастроек.Настройки.ПараметрыДанных.Элементы.Найти("ЗначениеПоиска");
Если ПараметрПоиска <> Неопределено Тогда
ПараметрПоиска.Значение = ПолеПоиска;
ПараметрПоиска.Использование = Истина;
КонецЕсли;
Если программисту нужно установить «жесткий» фильтр, который пользователю не требуется менять вручную в окне настроек списка, лучшим решением будет использование ФиксированныеНастройки. Рассмотрим их преимущество: они не синхронизируются с пользовательским интерфейсом настроек, что исключает накладные расходы на обновление UI-потока.
НовыйОтбор = Новый НастройкиКомпоновкиДанных;
Элемент = НовыйОтбор.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
Элемент.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Артикул");
Элемент.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
Элемент.ПравоеЗначение = ПолеПоиска;
Элемент.Использование = Истина;
Товары.ФиксированныеНастройки = НовыйОтбор;
Проанализируем еще несколько важных моментов, которые помогут ускорить работу динамического списка:
Основная таблица. Это позволит платформе использовать оптимизированные запросы для получения количества записей и навигации.Индексировать у реквизитов, по которым выполняется поиск.Динамическое считывание данных включено. Это позволит форме не блокироваться при ожидании полной выборки.&НаСервереБезКонтекста) может помочь диагностировать, где именно происходит задержка — в данных или в интерфейсе.Таким образом, зависание при установке ПравоеЗначение — это комплексная проблема, связанная с тем, как платформа 1С пытается «помочь» разработчику, синхронизируя настройки и обновляя данные в реальном времени. Используя вышеописанные методы оптимизации, мы можем добиться мгновенного отклика интерфейса даже при работе с очень большими справочниками товаров.