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