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