Как правильно организовать выполнение длительных операций в фоновом режиме в 1С 8.3 и получить результат?

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

В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью выполнения тяжелых вычислительных задач, которые занимают значительное время. Если выполнять такие операции в основном потоке клиентского приложения, интерфейс программы «зависает», что вызывает дискомфорт у пользователя и может привести к принудительному завершению сеанса операционной системой. Для решения этой проблемы мы используем механизм фоновых заданий. В данной статье мы подробно разберем, как запустить процедуру в фоне, передать ей параметры и, самое главное, вернуть результат обратно в форму.

Зачем нужны фоновые задания и как они работают

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

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

  1. Подготовка серверной процедуры в общем модуле.
  2. Запуск фонового задания с передачей параметров.
  3. Мониторинг состояния задания на клиенте с помощью обработчика ожидания.
  4. Получение и обработка результата после завершения.

Шаг 1. Создание серверной процедуры

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

Рассмотрим пример процедуры, которая выполняет длительный расчет и помещает результат во временное хранилище:


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

Шаг 2. Запуск фонового задания из формы

Теперь выясним, как инициировать запуск этой процедуры из управляемой формы. Нам понадобится метод ФоновыеЗадания.Выполнить(). Обратите внимание на формирование уникального адреса во временном хранилище — это критически важно для получения данных именно из нужного потока.

Разберем код запуска на стороне сервера в модуле формы:


&НаСервере
Функция ЗапуститьРасчетНаСервере()
    
    // Подготавливаем параметры для процедуры
    МассивПараметров = Новый Массив;
    МассивПараметров.Добавить(100);
    МассивПараметров.Добавить(200);
    
    // Генерируем уникальный идентификатор для временного хранилища
    АдресРезультата = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор);
    
    // Формируем массив аргументов для метода Выполнить
    АргументыЗадания = Новый Массив;
    АргументыЗадания.Добавить(МассивПараметров);
    АргументыЗадания.Добавить(АдресРезультата);
    
    // Запускаем задание
    ИмяМетода = "ОбщийМодульСервер.ВыполнитьДлительныйРасчет";
    Задание = ФоновыеЗадания.Выполнить(ИмяМетода, АргументыЗадания, , "МойДлительныйРасчет");
    
    Возврат Новый Структура("ИдентификаторЗадания, АдресРезультата", Задание.УникальныйИдентификатор, АдресРезультата);
    
КонецФункции

Шаг 3. Мониторинг состояния и получение результата

После запуска задания управление сразу возвращается пользователю. Чтобы понять, когда расчет завершен, нам нужно использовать ПодключитьОбработчикОжидания. Посмотрим на клиентскую логику:


&НаКлиенте
Перем ИдентификаторФоновогоЗадания;
Перем АдресХранилищаФоновогоЗадания;

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

&НаКлиенте
Процедура ПроверитьЗавершениеЗадания()
    
    Если ЗаданиеЗавершено(ИдентификаторФоновогоЗадания) Тогда
        ОтключитьОбработчикОжидания("ПроверитьЗавершениеЗадания");
        ПолучитьИОбработатьРезультат();
    КонецЕсли;
    
КонецПроцедуры

Нам также понадобится вспомогательная функция на сервере для проверки статуса задания по его GUID:


&НаСервереБезКонтекста
Функция ЗаданиеЗавершено(Идентификатор)
    Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Идентификатор);
    Возврат (Задание <> Неопределено И Задание.Состояние <> СостояниеФоновогоЗадания.Активно);
КонецФункции

Шаг 4. Чтение данных из временного хранилища

Когда задание переходит в состояние Завершено, мы можем извлечь данные по адресу, который передавали ранее. Проанализируем финальный этап:


&НаСервере
Процедура ПолучитьИОбработатьРезультат()
    
    // Получаем данные из хранилища
    Результат = ПолучитьИзВременногоХранилища(АдресХранилищаФоновогоЗадания);
    
    Если ТипЗнч(Результат) = Тип("Структура") Тогда
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Расчет окончен! Итог: " + Результат.ИтоговаяСумма;
        Сообщение.Сообщить();
    КонецЕсли;
    
КонецПроцедуры

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

В современных конфигурациях (ЕРП, УТ 11, БП 3.0) разработчики редко используют «чистые» фоновые задания. Рассмотрим более продвинутый метод через подсистему ДлительныеОперации. Это позволяет сократить объем кода и сделать обработку ошибок более надежной.

Посмотрим, как выглядит запуск через БСП:


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

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

Важные рекомендации и ограничения

При работе с фоновыми заданиями следует учитывать несколько критических моментов:

Таким образом, мы детально разобрали механизм асинхронной работы в 1С. Использование ФоновыеЗадания позволяет значительно повысить отзывчивость системы и лояльность пользователей, превращая «зависшие» отчеты в комфортные фоновые процессы.

← На главную