Почему зависает отладка на строке КонецПроцедуры при вызове с клиента на сервер?

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

Во время пошаговой отладки в управляемом приложении 1С разработчики нередко сталкиваются с ситуацией: замер производительности показывает мгновенное выполнение всех строк кода внутри процедуры, однако при нажатии F11 на финальной строке КонецПроцедуры отладчик «замирает» на 10–30 секунд. При этом стек вызовов не фиксирует новых вызовов методов. Разберем по шагам, какие процессы происходят в платформе в этот момент, почему возникает задержка и как её устранить.

Механизм возврата управления с сервера на клиент

Когда процедура с директивой &НаСервере вызывается из клиентского контекста, платформа выполняет комплексную работу по синхронизации состояния формы между тонким клиентом и сервером. На строке КонецПроцедуры серверная часть завершает исполнение алгоритма и начинает передачу данных обратно на клиентскую машину.

Проанализируем основные причины, вызывающие длительную паузу при возврате:

  1. Передача избыточного контекста формы: если процедура объявлена с директивой &НаСервере, на сервер отправляется весь контекст формы, а при завершении процедуры он сериализуется и передается обратно. Если в реквизитах формы хранятся тяжелые коллекции, таблицы значений или объемные структуры, процесс сериализации и передачи по сети занимает существенное время.
  2. Изменение метаданных динамического списка и сброс кэша формы: если внутри процедуры программно менялся текст запроса динамического списка, состав колонок или свойства элементов интерфейса (видимость, доступность, заголовки), клиентский кэш формы становится невалидным. Платформа вынуждена полностью пересчитывать структуру элементов управления.
  3. Первичная выборка данных динамического списка: при изменении текста запроса динамического списка возврат на клиент инициирует считывание первой порции данных (кванта). Если результирующий запрос содержит тяжелые левые соединения, виртуальные таблицы без параметров или не использует индексы, время ожидания выборки визуально накладывается на выход из процедуры.
  4. Особенности работы механизмов отладки: активные окна конфигуратора («Табло», «Локальные переменные») принудительно запрашивают значения всех доступных переменных на каждом шаге. Если в «Табло» вычислено тяжелое выражение, задержка связана с подготовкой отладочного дампа платформой.

Способ 1. Перевод вызовов на директиву БезКонтекста

Рассмотрим основной способ оптимизации серверных вызовов в управляемых формах. Если алгоритму не требуется модифицировать сам контекст формы (реквизиты и визуальные элементы), следует использовать директиву &НаСервереБезКонтекста. В этом случае между клиентом и сервером передаются строго те параметры, которые явно указаны в заголовке процедуры, что исключает сериализацию всей формы.

Посмотрим на пример рефакторинга кода:


// Неоптимальный подход: передается весь контекст формы
&НаСервере
Процедура ОбработатьДанныеНаСервере()
    // Код не использует реквизиты формы, но контекст передается целиком
    ВыполнитьТяжелыеРасчеты();
КонецПроцедуры

// Оптимальный подход: передаются только необходимые параметры
&НаСервереБезКонтекста
Процедура ОбработатьДанныеНаСервереБезКонтекста(Знач ВходнойПараметр)
    ВыполнитьТяжелыеРасчеты(ВходнойПараметр);
КонецПроцедуры

Способ 2. Правильная работа с динамическим списком

Проанализируем частую ошибку при работе с динамическими списками на сервере. Изменение свойства Список.ТекстЗапроса в рантайме заставляет платформу на клиенте заново перестраивать коллекцию колонок и очищать внутренние кэши. Вместо динамической склейки текста запроса необходимо использовать параметры и компоновщик настроек.

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


// Установка параметров без изменения текста запроса
Список.Параметры.УстановитьЗначениеПараметра("Организация", ВыбраннаяОрганизация);

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

Также важно убедиться, что для динамического списка в свойствах конфигуратора заполнено поле ОсновнаяТаблица и включен флаг Динамическое считывание данных. Это позволяет платформе считывать данные порциями и не блокировать интерфейс клиента сложными выборками при открытии и обновлении формы.

Способ 3. Использование временного хранилища для больших объемов данных

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

  1. На сервере помещаем сформированную таблицу во временное хранилище с привязкой к уникальному идентификатору формы.
  2. Возвращаем на клиент только строковый адрес хранилища.
  3. На клиенте получаем данные по мере реальной необходимости, избегая фоновой передачи тяжелых пакетов при завершении вызова.

&НаСервереБезКонтекста
Функция СформироватьТаблицуНаСервере(УникальныйИдентификаторФормы)
    ТаблицаРезультата = СформироватьСложныеДанные();
    АдресХранилища = ПоместитьВоВременноеХранилище(ТаблицаРезультата, УникальныйИдентификаторФормы);
    Возврат АдресХранилища;
КонецФункции

Способ 4. Диагностика показателей производительности и отладочного окружения

Выясним причину задержки с помощью встроенных инструментов платформы. Для точной оценки объема передаваемого трафика выполним следующие действия:

  1. В пользовательском режиме перейдем в меню: Главное меню → Настройки → Параметры и установим флаг Отображать показатели производительности (или запустим сеанс с ключом /DisplayPerformance).
  2. Посмотрим на счетчики в левом нижнем углу окна: они покажут количество вызовов сервера, время исполнения и точный объем переданных/принятых данных в байтах. Если на одну процедуру приходится передача нескольких мегабайт, проблема кроется в контексте формы.
  3. В конфигураторе очистим окно Табло и закроем панель Локальные переменные. Это исключит задержки самого отладчика при сериализации объектов памяти на шаге выхода из фрейма.
← На главную