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