При разработке регламентных процедур разработчики нередко сталкиваются с ситуацией, когда готовая бизнес-логика уже реализована в форме обработки — например, механизм взаимодействия с сервисом 1С:Контрагент, интеграция с внешними API или алгоритм с прогресс-баром. Возникает естественное желание переиспользовать существующий код и вызвать его из регламентного задания напрямую. Однако платформа 1С:Предприятие накладывает жесткие ограничения на контекст выполнения.
Разберем детально, почему клиентский код недоступен в регламентных заданиях и как правильно адаптировать логику длительных операций под серверное выполнение.
Регламентные и фоновые задания всегда выполняются на стороне сервера в неинтерактивном сеансе. В этом контексте полностью отсутствует клиентский уровень:
&НаКлиенте и методы клиентских общих модулей.ПодключитьОбработчикОжидания, Предупреждение, Вопрос или ОткрытьФорму.Попытка вызвать метод модуля формы или клиентский обработчик из серверного модуля приведет к синтаксической ошибке компиляции либо к аварийному завершению задания во время исполнения.
Проанализируем, как устроен типовой механизм длительных операций БСП на клиенте:
ДлительныеОперации.ЗапуститьВыполнениеВФоне(...)), который стартует фоновое задание на сервере.ПодключитьОбработчикОжидания, периодически проверяющий статус готовности данных.В контексте регламентного задания интерактивного пользователя нет, а серверный поток не требует разблокировки интерфейса. Соответственно, отслеживать завершение через клиентские таймеры не требуется.
Наиболее простое, быстрое и надежное решение для регламентного задания — вызов серверной процедуры напрямую без создания дополнительных фоновых заданий.
Выясним процедуру, которая передается в фоновое задание в форме обработки, и вызовем ее в синхронном режиме:
// В модуле объекта регламентного задания или общем модуле:
Процедура ВыполнитьРегламентнуюОбработку() Экспорт
// Получаем список контрагентов для актуализации
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Контрагенты.Ссылка КАК Контрагент,
| Контрагенты.ИНН КАК ИНН,
| Контрагенты.КПП КАК КПП
|ИЗ
| Справочник.Контрагенты КАК Контрагенты
|ГДЕ
| НЕ Контрагенты.ПометкаУдаления";
РезультатЗапроса = Запрос.Выполнить().Выгрузить();
Для Каждого Стр Из РезультатЗапроса Цикл
Попытка
// Вызываем серверную процедуру заполнения реквизитов напрямую
// без открытия формы и клиентских оберток
ЗаполнитьРеквизитыПоСервису(Стр.Контрагент, Стр.ИНН, Стр.КПП);
Исключение
ЗаписьЖурналаРегистрации(
"Обновление контрагентов",
УровеньЖурналаРегистрации.Ошибка,,,
"Ошибка обработки контрагента " + Строка(Стр.Контрагент) + ": " + ОписаниеОшибки()
);
КонецПопытки;
КонецЦикла;
КонецПроцедуры
Если логика жестко завязана на функции БСП и не может быть легко вынесена в синхронную процедуру, запустим процедуру через фоновое задание и дождемся его завершения серверными методами:
ПараметрыПроцедуры = Новый Структура;
ПараметрыПроцедуры.Вставить("ИНН", ТекущийИНН);
ПараметрыПроцедуры.Вставить("КПП", ТекущийКПП);
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(Неопределено);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = "Получение данных контрагента";
// Запуск фонового задания на сервере
ДлительнаяОперация = ДлительныеОперации.ЗапуститьВыполнениеВФоне(
"ЗаполнениеРеквизитовКонтрагентов.ЗаполнитьДанные",
ПараметрыПроцедуры,
ПараметрыВыполнения
);
// Ожидание завершения на сервере без клиентских обработчиков ожидания
Если ДлительнаяОперация.Статус = "Выполняется" Тогда
ПараметрыОжидания = ДлительныеОперации.ПараметрыОжидания(Неопределено);
ПараметрыОжидания.Таймаут = 60; // Максимальное время ожидания в секундах
ДлительныеОперации.ОжидатьЗавершение(ДлительнаяОперация, ПараметрыОжидания);
КонецЕсли;
Если ДлительнаяОперация.Статус = "Выполнено" Тогда
Результат = ПолучитьИзВременногоХранилища(ДлительнаяОперация.АдресРезультата);
// Запись полученных данных в регистр
КонецЕсли;
Также платформа предоставляет базовый метод ФоновыеЗадания.ОжидатьЗавершения(...), принимающий массив запущенных заданий и таймаут.
При настройке фонового обмена с сервисом 1С:Контрагент учтем следующие нюансы:
Попытка ... Исключение с фиксацией событий в ЖурналРегистрации, чтобы сбой по одному контрагенту не прерывал выполнение всего регламентного задания.