Как выполнить процедуру внешней обработки в фоновом задании

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

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

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

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

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

Способ 1: Использование подсистемы Дополнительные отчеты и обработки (БСП)

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

Разберем алгоритм действий:

  1. В модуле объекта внешней обработки должна присутствовать экспортная процедура ВыполнитьКоманду(ИдентификаторКоманды, ПараметрыВыполнения).
  2. Для запуска выполнения в фоне на стороне клиента используется метод ДополнительныеОтчетыИОбработкиКлиент.ВыполнитьКомандуВФоне().

Посмотрим на пример кода, который инициирует запуск:


ПараметрыВыполнения = ДополнительныеОтчетыИОбработкиКлиент.ПараметрыВыполненияКомандыВФоне(ВладелецФормы);
ПараметрыВыполнения.СообщениеОДлительнойОперации = "Выполняется проведение, подождите...";

ДополнительныеОтчетыИОбработкиКлиент.ВыполнитьКомандуВФоне(СсылкаНаОбработку, "ИмяКоманды", ПараметрыВыполнения);

В этом случае БСП сама извлечет двоичные данные обработки из справочника, создаст временный сеанс на сервере, подключит обработку и вызовет нужный метод. Это самый надежный и "правильный" путь для конфигураций на БСП.

Способ 2: Передача обработки через Временное хранилище

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

Рассмотрим пошагово, как это реализовать:

Шаг 1. Подготовка данных на стороне инициатора. Мы должны прочитать файл обработки в двоичные данные и поместить их в хранилище, адрес которого передадим в фоновое задание.


// На клиенте или сервере
ДвоичныеДанныеОбработки = Новый ДвоичныеДанные(ПутьКФайлуОбработки);
АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанныеОбработки, Новый УникальныйИдентификатор);

ПараметрыПроцедуры = Новый Структура;
ПараметрыПроцедуры.Вставить("АдресХранилища", АдресХранилища);
ПараметрыПроцедуры.Вставить("ДополнительныеПараметры", ВашиПараметры);

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

Шаг 2. Реализация серверного метода-прокладки. В общем модуле (например, ВашОбщийМодуль) необходимо создать экспортную процедуру, которая примет адрес хранилища, создаст объект обработки и запустит целевой метод.


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

Важные ограничения и нюансы

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

  1. Отсутствие интерфейса: В процедуре, выполняемой в фоне, категорически запрещено использование любых интерактивных методов: Сообщить() (в старом понимании), Вопрос(), Предупреждение(), ОткрытьФорму(). Если код проведения содержит такие вызовы, фоновое задание завершится с ошибкой. Для передачи сообщений пользователю используйте ОбщегоНазначения.СообщитьПользователю() или механизмы прогресса БСП.
  2. Безопасный режим: Внешние обработки часто подключаются в безопасном режиме. Это накладывает ограничения на использование некоторых методов (например, работу с файловой системой или COM-объектами). Если ваша процедура проведения требует расширенных прав, убедитесь, что при создании обработки в методе ВнешниеОбработки.Создать() вторым параметром передается Ложь (отключение безопасного режима), и у пользователя, под которым запускается фоновое задание, достаточно прав.
  3. Сериализация параметров: Все данные, которые вы передаете в структуру ПараметрыПроцедуры, должны быть сериализуемыми. Вы можете передать ссылки на справочники, числа, строки, структуры и массивы, но не можете передать, например, открытое соединение с базой данных или COM-объект.

Мониторинг выполнения

Для того чтобы пользователь видел, что происходит в фоне, рекомендуем использовать метод ДлительныеОперации.СообщитьПрогресс(). Выясним, как это работает: внутри процедуры внешней обработки вы можете периодически вызывать этот метод, передавая процент выполнения или текстовое сообщение. Основная форма, запустившая задание, сможет подхватить эти данные через обработчик ожидания и обновить индикатор на экране.

Проанализировав ситуацию, мы видим, что наиболее элегантным решением является встраивание обработки в справочник БСП. Это избавляет от необходимости вручную манипулировать временными файлами и хранилищами, обеспечивая при этом высокий уровень безопасности и стабильности системы.

← На главную