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