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

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

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

Понятие и назначение фоновых заданий

Для начала выясним причину блокировки интерфейса. В управляемом приложении клиентский сеанс ожидает завершения серверного вызова. Если сервер выполняет процедуру 10 минут, клиент все это время будет «висеть». Рассмотрим основной способ обхода этого ограничения — использование объекта ФоновыеЗадания. Этот механизм позволяет серверу создать отдельный поток (сеанс), который будет выполнять код независимо от основного сеанса пользователя — для управления такими потоками есть готовые инструменты для управления и анализа фоновых заданий. Разберем по шагам, как это реализовать.

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

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

Посмотрим на пример структуры такой процедуры:


Процедура ВыполнитьТяжелыйРасчет(ПараметрыРасчета, АдресРезультата) Экспорт
    // Выполняем длительные действия
    Результат = Новый Структура;
    // ... логика расчета ...
    
    // Помещаем результат во временное хранилище, чтобы забрать его позже
    ПоместитьВоВременноеХранилище(Результат, АдресРезультата);
КонецПроцедуры

Обратим внимание на использование АдресРезультата. Поскольку фоновое задание работает в другом сеансе, передать данные напрямую через переменные невозможно. Мы используем временное хранилище с привязкой к идентификатору формы или уникальному идентификатору.

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

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


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

Шаг 3. Мониторинг состояния и ожидание завершения

После запуска задания нам нужно периодически проверять, завершилось оно или нет, чтобы вывести результат пользователю. Для этого на форме удобно использовать ПодключитьОбработчикОжидания. Это позволит системе проверять статус задания через определенные интервалы времени (например, каждые 2-3 секунды), не блокируя работу человека. Если запуск должен происходить по сложному графику, вам может пригодиться конструктор Cron расписания для точной настройки времени выполнения.

Проанализируем алгоритм проверки:


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

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

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

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

Если ваша конфигурация построена на базе БСП (как большинство современных типовых решений: 1C:ERP, УТ 11, БП 3.0), мы рекомендуем использовать модуль ДлительныеОперации. Это значительно упрощает разработку, так как библиотека уже содержит готовые механизмы визуализации (индикатор загрузки, модальные окна ожидания). Обязательно изучите использование длительных операций в БСП 3.1.8, чтобы использовать актуальные для последних версий алгоритмы.

Рассмотрим, как запустить операцию через БСП:


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

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

Особенности и ограничения

Выясним несколько критических нюансов, которые помогут избежать ошибок при работе с фоновыми заданиями:

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

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

← На главную