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