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

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

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

Подготовка и основной код для запуска

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

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

Давайте посмотрим на пример кода для запуска:


Процедура Команда1(Команда)
    // Имя метода должно содержать ИмяОбщегоМодуля.ИмяПроцедуры
    ИмяМетода = "ОбщийМодуль.ПроцедураФоновогоЗадания"; 
    
    // Создаем массив параметров для передачи в процедуру
    МассивПараметров = Новый Массив; 
    МассивПараметров.Добавить("Параметр1");
    МассивПараметров.Добавить(123);
    
    // Непосредственный запуск фонового задания
    ФоновоеЗадание = ФоновыеЗадания.Выполнить(
        ИмяМетода, 
        МассивПараметров, 
        , // Ключ
        "Это Наименование фонового задания"); // Имя

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

Разберем этот код по шагам:

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

Разбираемся с параметрами: Имя, Ключ и Идентификатор

В методе Выполнить() есть два важных параметра, которые часто вызывают путаницу: Имя и Ключ. Давайте разберемся, в чем их отличие и для чего каждый из них нужен.

Имя (Наименование)

Это четвертый параметр метода Выполнить(). Имя – это простое текстовое описание, которое будет отображаться для пользователя в консоли заданий. Его основная задача – помочь администратору или пользователю понять, что это за задание. Имена могут быть неуникальными; вы можете запустить сколько угодно заданий с одинаковым именем.

В коде это выглядит так:

ФоновыеЗадания.Выполнить(..., , "Выгрузка данных по контрагенту ООО 'Ромашка'");

Ключ

Это третий параметр метода. Ключ – это строковый программный идентификатор, который используется для обеспечения уникальности выполняемых заданий. Если вы попытаетесь запустить фоновое задание с ключом, который уже используется другим активным (выполняемым) заданием, то новый запуск не произойдет, и метод Выполнить() вернет Неопределено.

Ключевое свойство ключа: он гарантирует, что в один момент времени будет выполняться только одно задание с таким ключом. Это невероятно полезно, чтобы избежать дублирования операций. Например, если пользователь случайно нажмет кнопку "Сформировать отчет" дважды, второе задание не запустится, пока не завершится первое (если у них одинаковый ключ).

Пример использования ключа для предотвращения дублей:


// Создаем уникальный ключ на основе данных
КлючЗадания = "ВыгрузкаПрайсЛиста_" + Формат(ТекущаяДата(), "ДФ=ггггММдд");

// Пытаемся запустить задание
Задание = ФоновыеЗадания.Выполнить(
    "МодульОбмена.ВыгрузитьПрайсЛист",
    Параметры,
    КлючЗадания,
    "Ежедневная выгрузка прайс-листа");
    
Если Задание = Неопределено Тогда
    Сообщить("Выгрузка прайс-листа на сегодня уже запущена. Дождитесь ее завершения.");
КонецЕсли;

УникальныйИдентификатор

Помимо Имени и Ключа, каждое успешно созданное фоновое задание получает УникальныйИдентификатор (GUID). Это абсолютный идентификатор конкретного экземпляра задания. Метод Выполнить() возвращает объект ФоновоеЗадание, у которого есть свойство УникальныйИдентификатор. Этот идентификатор следует сохранять, если вы планируете в дальнейшем отслеживать состояние именно этого запуска (завершилось ли оно, есть ли ошибки и т.д.).

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

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

Шаг 1. Процедура для фонового выполнения в общем модуле.

Создадим общий модуль, например, ДлительныеОперацииСервер, и установим ему флаги "Сервер" и "Внешнее соединение". Внутри него разместим экспортную процедуру.


// Общий модуль ДлительныеОперацииСервер

&НаСервере
&НаСервереБезКонтекста
Процедура СформироватьОтчет(ИдентификаторОтчета, ДатаНачала, ДатаОкончания) Экспорт

    // Имитация длительной работы
    Для сч = 1 по 100 Цикл
        // Здесь выполняется сложная логика: запросы, расчеты и т.д.
        Пауза(1); 
    КонецЦикла;
    
    // Здесь мог бы быть код сохранения результата в какой-нибудь регистр
    
КонецПроцедуры

Шаг 2. Код запуска и проверки состояния.

Этот код может быть размещен в обработке или в команде формы.


&НаКлиенте
Процедура ЗапуститьФормированиеОтчета(Команда)
    // Запускаем серверную процедуру для создания фонового задания
    ИдентификаторЗадания = ЗапуститьФормированиеОтчетаНаСервере();
    
    Если ИдентификаторЗадания <> Неопределено Тогда
        Сообщить("Отчет начал формироваться в фоновом режиме. Ожидайте завершения.");
        // Можно сохранить ИдентификаторЗадания для последующих проверок
    Иначе
        Предупреждение("Не удалось запустить формирование отчета. Возможно, он уже выполняется.");
    КонецЕсли;
КонецПроцедуры


&НаСервере
Функция ЗапуститьФормированиеОтчетаНаСервере()
    
    ИмяМетода = "ДлительныеОперацииСервер.СформироватьОтчет";
    
    Параметры = Новый Массив;
    Параметры.Добавить(Новый УникальныйИдентификатор()); // Параметр 1: ИдентификаторОтчета
    Параметры.Добавить(НачалоГода(ТекущаяДата()));     // Параметр 2: ДатаНачала
    Параметры.Добавить(КонецГода(ТекущаяДата()));       // Параметр 3: ДатаОкончания

    // Ключ для предотвращения повторного запуска
    КлючЗадания = "ФормированиеГодовогоОтчета";
    
    Наименование = "Формирование годового отчета для руководства";
    
    Попытка
        ЗапущенноеЗадание = ФоновыеЗадания.Выполнить(
            ИмяМетода, 
            Параметры, 
            КлючЗадания, 
            Наименование);
    Исключение
        // Обработка ошибок, если модуль или метод не найден
        ЗаписьЖурналаРегистрации("ФоновыеЗадания", УровеньЖурналаРегистрации.Ошибка, , , ОписаниеОшибки());
        Возврат Неопределено;
    КонецПопытки;
    
    Если ЗапущенноеЗадание = Неопределено Тогда
        Возврат Неопределено;
    Иначе
        // Возвращаем GUID для дальнейшего контроля
        Возврат ЗапущенноеЗадание.УникальныйИдентификатор;
    КонецЕсли;
    
КонецФункции

Используя полученный ИдентификаторЗадания, вы можете в любой другой момент времени проверить его статус с помощью метода ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ВашИдентификатор). Этот метод вернет объект ФоновоеЗадание, из которого можно будет прочитать свойство Состояние (например, СостояниеФоновогоЗадания.Завершено, СостояниеФоновогоЗадания.Ошибка) — для автоматического контроля ошибок есть готовая система мониторинга фоновых заданий с уведомлениями. Если ваша конфигурация не использует БСП, вы можете реализовать отслеживание результата выполнения и индикацию прогресса без БСП собственными силами.

Таким образом, программная работа с фоновыми заданиями предоставляет мощный механизм для оптимизации производительности и улучшения пользовательского опыта в системах 1С. А чтобы сделать процесс разработки еще комфортнее, можно использовать ускоритель работы программиста, который оповестит вас о завершении длительных операций в конфигураторе или предприятии — для этого есть готовый набор инструментов разработчика для управления фоновыми заданиями.

← На главную