Как запустить экспортную процедуру обработки в фоновом задании 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке универсальных обработок часто возникает задача вынести длительные вычисления в фоновый режим. При этом разработчики сталкиваются с ограничением платформы 1С:Предприятие: запустить метод объекта обработки напрямую через ФоновыеЗадания.Выполнить нельзя, так как данный метод требует строгой сигнатуры серверного неглобального общего модуля. Попытка передать конструкцию вида "Обработки.МояОбработка.Создать.МойМетод" приводит к ошибке Метод задания не найден.

Разберем причины такого поведения платформы, а также рассмотрим практические способы запуска процедур в фоне как для внешних обработок, так и для обработок, встроенных в конфигурацию.

Почему возникает ошибка при прямом вызове метода обработки в фоне?

Проанализируем ограничения платформы 1С и принципы работы подсистемы фоновых заданий:

  1. Ограничение метода ФоновыеЗадания.Выполнить: платформа на низком уровне принимает в качестве имени метода только экспортные процедуры неглобальных серверных общих модулей в формате "ИмяОбщегоМодуля.ИмяПроцедуры". Платформа не создает динамически экземпляр объекта по составным строковым путям.
  2. Изоляция серверных сеансов: фоновое задание всегда стартует в отдельном изолированном серверном сеансе. В нем нет контекста клиентского сеанса и не существует предварительно созданного экземпляра объекта обработки. Поэтому все параметры, передаваемые в задание, должны быть строго сериализуемыми типами (числа, строки, ссылки, структуры, массивы).
  3. Безопасный режим: при исполнении кода внешних обработок в фоновых заданиях платформа и БСП контролируют профили безопасности и флаг безопасного режима, что может ограничивать доступ к привилегированным операциям.

Способ 1. Использование процедуры БСП ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки

В Библиотеке стандартных подсистем (БСП) реализован универсальный механизм-обертка, который позволяет исполнять код как внешней, так и встроенной обработки без создания отдельного общего модуля под каждую задачу.

Рассмотрим структуру типовой процедуры модуля ДлительныеОперации:


Процедура ВыполнитьПроцедуруМодуляОбъектаОбработки(Параметры, АдресХранилища) Экспорт
    
    ИмяМетода = Параметры.ИмяМетода;
    
    // Проверка корректности имени метода
    ВременнаяСтруктура = Новый Структура;
    Попытка
        ВременнаяСтруктура.Вставить(ИмяМетода);
    Исключение
        ЗаписьЖурналаРегистрации(
            НСтр("ru = 'Безопасное выполнение метода обработки'"), 
            УровеньЖурналаРегистрации.Ошибка, , , 
            ПодробноеПредставлениеОшибки(ИнформацияОбОшибке()));
        ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
            НСтр("ru='Имя метода ""%1"" не соответствует требованиям образования имен переменных.'"), 
            ИмяМетода);
    КонецПопытки;

    ПараметрыВыполнения = Параметры.ПараметрыВыполнения;

    Если Параметры.ЭтоВнешняяОбработка Тогда
        Если ЗначениеЗаполнено(Параметры.ДополнительнаяОбработкаСсылка) 
            И ОбщегоНазначения.ПодсистемаСуществует("СтандартныеПодсистемы.ДополнительныеОтчетыИОбработки") Тогда
            
            МодульДополнительныеОтчетыИОбработки = ОбщегоНазначения.ОбщийМодуль("ДополнительныеОтчетыИОбработки");
            Обработка = МодульДополнительныеОтчетыИОбработки.ПолучитьОбъектВнешнейОбработки(Параметры.ДополнительнаяОбработкаСсылка);
        Иначе
            Обработка = ВнешниеОбработки.Создать(Параметры.ИмяОбработки);
        КонецЕсли;
    Иначе
        Обработка = Обработки[Параметры.ИмяОбработки].Создать();
    КонецЕсли;

    Выполнить("Обработка." + ИмяМетода + "(ПараметрыВыполнения, АдресХранилища)");

КонецПроцедуры

Посмотрим на пример вызова данной процедуры через механизм длительных операций:


ПараметрыПроцедуры = Новый Структура;
ПараметрыПроцедуры.Вставить("ЭтоВнешняяОбработка", Ложь);
ПараметрыПроцедуры.Вставить("ИмяОбработки", "МояОбработка");
ПараметрыПроцедуры.Вставить("ИмяМетода", "ЭкспортныйМетодОбработки");
ПараметрыПроцедуры.Вставить("ПараметрыВыполнения", Новый Структура("СписокАдресов", СписокАдресов));

ПараметрыЗадания = Новый Массив;
ПараметрыЗадания.Добавить(ПараметрыПроцедуры);
ПараметрыЗадания.Добавить(Неопределено); // Адрес во временном хранилище

ФоновыеЗадания.Выполнить("ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки", ПараметрыЗадания);

Способ 2. Вызов метода через модуль менеджера встроенной обработки

Если обработка внедрена в состав конфигурации или добавлена через расширение (.cfe), наиболее архитектурно правильным и быстрым решением является перенос фоновой логики в модуль менеджера обработки.

Разберем по шагам, почему это работает:

  1. Механизмы ДлительныеОперации.ВыполнитьВФоне и ФоновыеЗадания.Выполнить умеют адресовать методы менеджеров объектов конфигурации.
  2. Имя метода передается в виде "Обработки.<ИмяОбработки>.<ИмяЭкспортнойПроцедуры>".
  3. В отличие от модуля объекта, менеджер не требует создания экземпляра через Создать(), что снижает накладные расходы и упрощает валидацию имени метода подсистемами безопасности БСП.

Посмотрим на пример реализации в модуле менеджера встроенной обработки Обработки.МояОбработка:


// В модуле менеджера обработки:
Процедура ЗапуститьРасчетВФоне(Параметры, АдресРезультата) Экспорт
    
    // Выполняем требуемый алгоритм
    Результат = Новый Структура;
    Результат.Вставить("Статус", "Успешно");
    
    Если ЗначениеЗаполнено(АдресРезультата) Тогда
        ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
    КонецЕсли;
    
КонецПроцедуры

Запуск такого метода через подсистему длительных операций БСП выполняется стандартно:


ПараметрыОперации = Новый Структура("Параметр1", Значение1);
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);

ДлительнаяОперация = ДлительныеОперации.ВыполнитьВФоне(
    "Обработки.МояОбработка.ЗапуститьРасчетВФоне",
    ПараметрыОперации,
    ПараметрыВыполнения
);

Способ 3. Запуск внешней обработки через подсистему ДополнительныеОтчетыИОбработки

Если обработка подключается как внешняя через справочник ДополнительныеОтчетыИОбработки, БСП предоставляет встроенную поддержку запуска команд в фоне по расписанию или по кнопке.

В модуле объекта внешней обработки необходимо реализовать функцию СведенияОВнешнейОбработке с указанием безопасного режима и варианта запуска:


Функция СведенияОВнешнейОбработке() Экспорт

    ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.0");
    ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
    ПараметрыРегистрации.Версия = "1.0";
    ПараметрыРегистрации.БезопасныйРежим = Ложь; // Требуется, если фоновое задание обращается к привилегированным операциям

    ТаблицаКоманд = ПараметрыРегистрации.Команды;
    
    СтрокаКоманды = ТаблицаКоманд.Добавить();
    СтрокаКоманды.Представление = НСтр("ru = 'Выполнить обработку данных в фоне'");
    СтрокаКоманды.Идентификатор = "ФоноваяКоманда";
    СтрокаКоманды.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();
    СтрокаКоманды.ПоказыватьОповещение = Истина;

    Возврат ПараметрыРегистрации;

КонецФункции

Процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыКоманды) Экспорт
    Если ИдентификаторКоманды = "ФоноваяКоманда" Тогда
        // Логика фоновой обработки данных
    КонецЕсли;
КонецПроцедуры

Итоги

Для запуска фоновых процедур из обработок выбирайте подход в зависимости от варианта использования:

  1. Для встроенных в конфигурацию обработок — размещайте фоновый код в модуле менеджера и вызывайте его через ДлительныеОперации.ВыполнитьВФоне("Обработки.Имя.Метод", ...).
  2. Для внешних обработок — подключайте их через подсистему ДополнительныеОтчетыИОбработки либо используйте универсальную процедуру ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки.
  3. Если требуется полная изоляция без изменения основной конфигурации — выносите обработку и вспомогательный серверный модуль в расширение конфигурации (.cfe).
← На главную