В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью выполнения тяжелых вычислительных задач, которые занимают значительное время. Если выполнять такие операции в основном потоке клиентского приложения, интерфейс программы «зависает», что вызывает дискомфорт у пользователя и может привести к принудительному завершению сеанса операционной системой. Для решения этой проблемы мы используем механизм фоновых заданий. В данной статье мы подробно разберем, как запустить процедуру в фоне, передать ей параметры и, самое главное, вернуть результат обратно в форму.
Разберем основной принцип: фоновое задание — это отдельный сеанс на сервере 1С, который выполняется параллельно с основным сеансом пользователя. Основной сеанс при этом остается свободным для взаимодействия с интерфейсом. Важно понимать, что фоновое задание не имеет прямого доступа к экранным формам или объектам, созданным в сеансе пользователя. Взаимодействие между ними происходит через базу данных или временное хранилище.
Проанализируем основные этапы реализации этой задачи:
Прежде всего, создадим процедуру, которую мы хотим выполнить. Она должна располагаться в общем модуле с установленными свойствами Сервер и Вызов сервера (либо доступном для вызова с сервера). Важно помнить: параметры в фоновое задание передаются в виде массива.
Рассмотрим пример процедуры, которая выполняет длительный расчет и помещает результат во временное хранилище:
Процедура ВыполнитьДлительныйРасчет(Параметры, АдресХранилища) Экспорт
// Параметры — это структура или массив, переданный при запуске
// АдресХранилища — уникальный адрес, куда мы запишем результат
РезультатРасчета = Новый Структура;
Сумма = 0;
Для Каждого ТекущийПараметр Из Параметры Цикл
// Эмуляция длительной работы
Сумма = Сумма + ТекущийПараметр;
КонецЦикла;
РезультатРасчета.Вставить("ИтоговаяСумма", Сумма);
РезультатРасчета.Вставить("Статус", "Успешно");
// Помещаем результат, чтобы клиент мог его забрать
ПоместитьВоВременноеХранилище(РезультатРасчета, АдресХранилища);
КонецПроцедуры
Теперь выясним, как инициировать запуск этой процедуры из управляемой формы. Нам понадобится метод ФоновыеЗадания.Выполнить(). Обратите внимание на формирование уникального адреса во временном хранилище — это критически важно для получения данных именно из нужного потока.
Разберем код запуска на стороне сервера в модуле формы:
&НаСервере
Функция ЗапуститьРасчетНаСервере()
// Подготавливаем параметры для процедуры
МассивПараметров = Новый Массив;
МассивПараметров.Добавить(100);
МассивПараметров.Добавить(200);
// Генерируем уникальный идентификатор для временного хранилища
АдресРезультата = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор);
// Формируем массив аргументов для метода Выполнить
АргументыЗадания = Новый Массив;
АргументыЗадания.Добавить(МассивПараметров);
АргументыЗадания.Добавить(АдресРезультата);
// Запускаем задание
ИмяМетода = "ОбщийМодульСервер.ВыполнитьДлительныйРасчет";
Задание = ФоновыеЗадания.Выполнить(ИмяМетода, АргументыЗадания, , "МойДлительныйРасчет");
Возврат Новый Структура("ИдентификаторЗадания, АдресРезультата", Задание.УникальныйИдентификатор, АдресРезультата);
КонецФункции
После запуска задания управление сразу возвращается пользователю. Чтобы понять, когда расчет завершен, нам нужно использовать ПодключитьОбработчикОжидания. Посмотрим на клиентскую логику:
&НаКлиенте
Перем ИдентификаторФоновогоЗадания;
Перем АдресХранилищаФоновогоЗадания;
&НаКлиенте
Процедура КомандаЗапуска(Команда)
ДанныеЗадания = ЗапуститьРасчетНаСервере();
ИдентификаторФоновогоЗадания = ДанныеЗадания.ИдентификаторЗадания;
АдресХранилищаФоновогоЗадания = ДанныеЗадания.АдресРезультата;
// Подключаем проверку каждые 2 секунды
ПодключитьОбработчикОжидания("ПроверитьЗавершениеЗадания", 2);
Состояние("Выполняется расчет, подождите...");
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьЗавершениеЗадания()
Если ЗаданиеЗавершено(ИдентификаторФоновогоЗадания) Тогда
ОтключитьОбработчикОжидания("ПроверитьЗавершениеЗадания");
ПолучитьИОбработатьРезультат();
КонецЕсли;
КонецПроцедуры
Нам также понадобится вспомогательная функция на сервере для проверки статуса задания по его GUID:
&НаСервереБезКонтекста
Функция ЗаданиеЗавершено(Идентификатор)
Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(Идентификатор);
Возврат (Задание <> Неопределено И Задание.Состояние <> СостояниеФоновогоЗадания.Активно);
КонецФункции
Когда задание переходит в состояние Завершено, мы можем извлечь данные по адресу, который передавали ранее. Проанализируем финальный этап:
&НаСервере
Процедура ПолучитьИОбработатьРезультат()
// Получаем данные из хранилища
Результат = ПолучитьИзВременногоХранилища(АдресХранилищаФоновогоЗадания);
Если ТипЗнч(Результат) = Тип("Структура") Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Расчет окончен! Итог: " + Результат.ИтоговаяСумма;
Сообщение.Сообщить();
КонецЕсли;
КонецПроцедуры
В современных конфигурациях (ЕРП, УТ 11, БП 3.0) разработчики редко используют «чистые» фоновые задания. Рассмотрим более продвинутый метод через подсистему ДлительныеОперации. Это позволяет сократить объем кода и сделать обработку ошибок более надежной.
Посмотрим, как выглядит запуск через БСП:
&НаСервере
Функция ЗапуститьЧерезБСП()
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = "Тестовый расчет через БСП";
РезультатЗапуска = ДлительныеОперации.ВыполнитьВФоне(
"ОбщийМодульСервер.ВыполнитьДлительныйРасчет",
МассивПараметров,
ПараметрыВыполнения
);
Возврат РезультатЗапуска;
КонецФункции
Преимущество БСП заключается в том, что функция ДлительныеОперации.ОжидатьЗавершения() может автоматически обрабатывать прогресс выполнения и корректно завершать сеансы при закрытии формы пользователем. Это избавляет нас от ручного управления обработчиками ожидания в простых сценариях.
При работе с фоновыми заданиями следует учитывать несколько критических моментов:
СправочникОбъект, ДокументОбъект), так как они не сериализуются. Используйте Ссылку или структуры с данными.ИнформацияОбОшибке объекта ФоновоеЗадание, чтобы уведомить пользователя.Таким образом, мы детально разобрали механизм асинхронной работы в 1С. Использование ФоновыеЗадания позволяет значительно повысить отзывчивость системы и лояльность пользователей, превращая «зависшие» отчеты в комфортные фоновые процессы.