При разработке универсальных обработок часто возникает задача вынести длительные вычисления в фоновый режим. При этом разработчики сталкиваются с ограничением платформы 1С:Предприятие: запустить метод объекта обработки напрямую через ФоновыеЗадания.Выполнить нельзя, так как данный метод требует строгой сигнатуры серверного неглобального общего модуля. Попытка передать конструкцию вида "Обработки.МояОбработка.Создать.МойМетод" приводит к ошибке Метод задания не найден.
Разберем причины такого поведения платформы, а также рассмотрим практические способы запуска процедур в фоне как для внешних обработок, так и для обработок, встроенных в конфигурацию.
Проанализируем ограничения платформы 1С и принципы работы подсистемы фоновых заданий:
"ИмяОбщегоМодуля.ИмяПроцедуры". Платформа не создает динамически экземпляр объекта по составным строковым путям.В Библиотеке стандартных подсистем (БСП) реализован универсальный механизм-обертка, который позволяет исполнять код как внешней, так и встроенной обработки без создания отдельного общего модуля под каждую задачу.
Рассмотрим структуру типовой процедуры модуля ДлительныеОперации:
Процедура ВыполнитьПроцедуруМодуляОбъектаОбработки(Параметры, АдресХранилища) Экспорт
ИмяМетода = Параметры.ИмяМетода;
// Проверка корректности имени метода
ВременнаяСтруктура = Новый Структура;
Попытка
ВременнаяСтруктура.Вставить(ИмяМетода);
Исключение
ЗаписьЖурналаРегистрации(
НСтр("ru = 'Безопасное выполнение метода обработки'"),
УровеньЖурналаРегистрации.Ошибка, , ,
ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru='Имя метода ""%1"" не соответствует требованиям образования имен переменных.'"),
ИмяМетода);
КонецПопытки;
ПараметрыВыполнения = Параметры.ПараметрыВыполнения;
Если Параметры.ЭтоВнешняяОбработка Тогда
Если ЗначениеЗаполнено(Параметры.ДополнительнаяОбработкаСсылка)
И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ДополнительныеОтчетыИОбработки") Тогда
МодульДополнительныеОтчетыИОбработки = ОбщегоНазначения.ОбщийМодуль("ДополнительныеОтчетыИОбработки");
Обработка = МодульДополнительныеОтчетыИОбработки.ПолучитьОбъектВнешнейОбработки(Параметры.ДополнительнаяОбработкаСсылка);
Иначе
Обработка = ВнешниеОбработки.Создать(Параметры.ИмяОбработки);
КонецЕсли;
Иначе
Обработка = Обработки[Параметры.ИмяОбработки].Создать();
КонецЕсли;
Выполнить("Обработка." + ИмяМетода + "(ПараметрыВыполнения, АдресХранилища)");
КонецПроцедуры
Посмотрим на пример вызова данной процедуры через механизм длительных операций:
ПараметрыПроцедуры = Новый Структура;
ПараметрыПроцедуры.Вставить("ЭтоВнешняяОбработка", Ложь);
ПараметрыПроцедуры.Вставить("ИмяОбработки", "МояОбработка");
ПараметрыПроцедуры.Вставить("ИмяМетода", "ЭкспортныйМетодОбработки");
ПараметрыПроцедуры.Вставить("ПараметрыВыполнения", Новый Структура("СписокАдресов", СписокАдресов));
ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(ПараметрыПроцедуры);
ПараметрыЗадания.Добавить(Неопределено); // Адрес во временном хранилище
ФоновыеЗадания.Выполнить("ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки", ПараметрыЗадания);
Если обработка внедрена в состав конфигурации или добавлена через расширение (.cfe), наиболее архитектурно правильным и быстрым решением является перенос фоновой логики в модуль менеджера обработки.
Разберем по шагам, почему это работает:
ДлительныеОперации.ВыполнитьВФоне и ФоновыеЗадания.Выполнить умеют адресовать методы менеджеров объектов конфигурации."Обработки.<ИмяОбработки>.<ИмяЭкспортнойПроцедуры>".Создать(), что снижает накладные расходы и упрощает валидацию имени метода подсистемами безопасности БСП.Посмотрим на пример реализации в модуле менеджера встроенной обработки Обработки.МояОбработка:
// В модуле менеджера обработки:
Процедура ЗапуститьРасчетВФоне(Параметры, АдресРезультата) Экспорт
// Выполняем требуемый алгоритм
Результат = Новый Структура;
Результат.Вставить("Статус", "Успешно");
Если ЗначениеЗаполнено(АдресРезультата) Тогда
ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
КонецЕсли;
КонецПроцедуры
Запуск такого метода через подсистему длительных операций БСП выполняется стандартно:
ПараметрыОперации = Новый Структура("Параметр1", Значение1);
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
ДлительнаяОперация = ДлительныеОперации.ВыполнитьВФоне(
"Обработки.МояОбработка.ЗапуститьРасчетВФоне",
ПараметрыОперации,
ПараметрыВыполнения
);
Если обработка подключается как внешняя через справочник ДополнительныеОтчетыИОбработки, БСП предоставляет встроенную поддержку запуска команд в фоне по расписанию или по кнопке.
В модуле объекта внешней обработки необходимо реализовать функцию СведенияОВнешнейОбработке с указанием безопасного режима и варианта запуска:
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.0");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
ПараметрыРегистрации.Версия = "1.0";
ПараметрыРегистрации.БезопасныйРежим = Ложь; // Требуется, если фоновое задание обращается к привилегированным операциям
ТаблицаКоманд = ПараметрыРегистрации.Команды;
СтрокаКоманды = ТаблицаКоманд.Добавить();
СтрокаКоманды.Представление = НСтр("ru = 'Выполнить обработку данных в фоне'");
СтрокаКоманды.Идентификатор = "ФоноваяКоманда";
СтрокаКоманды.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
СтрокаКоманды.ПоказыватьОповещение = Истина;
Возврат ПараметрыРегистрации;
КонецФункции
Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыКоманды) Экспорт
Если ИдентификаторКоманды = "ФоноваяКоманда" Тогда
// Логика фоновой обработки данных
КонецЕсли;
КонецПроцедуры
Для запуска фоновых процедур из обработок выбирайте подход в зависимости от варианта использования:
ДлительныеОперации.ВыполнитьВФоне("Обработки.Имя.Метод", ...).ДополнительныеОтчетыИОбработки либо используйте универсальную процедуру ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки.