В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает классическая задача: необходимо выполнить длительную обработку данных на сервере и при этом информировать пользователя о текущем состоянии процесса в режиме реального времени. Если запустить процедуру обычным способом, интерфейс программы «зависает» до завершения выполнения, и пользователь не видит никакой обратной связи. В этой статье мы разберем современные и надежные способы решения этой задачи, от стандартных механизмов БСП до использования Системы взаимодействия.
Рассмотрим ситуацию, представленную в исходном вопросе. Когда мы вызываем серверную процедуру ПометитьНаУдаление() напрямую из клиентской команды, происходит блокировка основного потока интерфейса. Пока сервер не закончит перебор всех контрагентов и не вернет управление клиенту, форма не будет перерисована. Любые попытки вызвать внутри такого цикла метод Состояние() или обновить реквизиты формы не дадут визуального эффекта до самого конца операции. Для решения этой проблемы нам необходимо перевести операцию в асинхронный режим.
Разберем самый распространенный технический подход. Суть его заключается в том, что длительная операция запускается в отдельном потоке (фоновом задании), а клиентская форма периодически «опрашивает» сервер о состоянии этого задания.
Для реализации этого механизма выполним следующие шаги:
ФоновыеЗадания.Выполнить(), передавая имя нашей экспортной процедуры и параметры.ПодключитьОбработчикОжидания().Посмотрим на пример реализации кода для серверной части:
&НаСервере
Функция ЗапуститьОбработкуНаСервере()
ПараметрыПроцедуры = Новый Структура;
// Адрес, куда фоновое задание будет писать прогресс
АдресРезультата = ПоместитьВоВременноеХранилище(Неопределено, ЭтаФорма.УникальныйИдентификатор);
РезультатЗапуска = ФоновыеЗадания.Выполнить("МойОбщийМодуль.ВыполнитьДлительнуюОперацию",
Новый Массив, , "Обработка контрагентов");
Возврат Новый Структура("ИдентификаторЗадания, АдресРезультата",
РезультатЗапуска.УникальныйИдентификатор, АдресРезультата);
КонецФункции
Проанализируем работу фонового задания. Внутри процедуры ВыполнитьДлительнуюОперацию мы должны периодически обновлять данные в хранилище:
Процедура ВыполнитьДлительнуюОперацию(Параметры, АдресРезультата) Экспорт
Выборка = Справочники.Контрагенты.Выбрать();
Всего = Выборка.Количество();
Счетчик = 0;
Пока Выборка.Следующий() Цикл
// Основная логика
Счетчик = Счетчик + 1;
// Обновляем прогресс каждые 10 итераций для экономии ресурсов
Если Счетчик % 10 = 0 Тогда
Прогресс = (Счетчик / Всего) * 100;
ПоместитьВоВременноеХранилище(Прогресс, АдресРезультата);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), крайне рекомендуется использовать встроенный модуль ДлительныеОперации. Это «кошерный» способ, который уже содержит все необходимые механизмы обработки ошибок и управления сеансами.
Рассмотрим основные преимущества использования БСП:
Для реализации через БСП мы используем функцию ДлительныеОперации.ЗапуститьВыполнениеНаСервере(). На клиенте выполнение контролируется через процедуру ДлительныеОперацииКлиент.ОжидатьЗавершения(). Это позволяет реализовать сценарий, когда пользователь видит модальное окно с прогресс-баром и кнопкой отмены.
Выясним причину, по которой этот метод считается наиболее современным. В отличие от предыдущих способов, где клиент «тянет» данные с сервера (Pull), Система взаимодействия позволяет серверу самому «толкать» данные на клиент (Push) через протокол WebSocket.
Проанализируем шаги для внедрения этого метода:
ПодключитьОбработчикОжиданияСистемыВзаимодействия() или через обработку события ПриПолученииСообщения.Этот метод идеален, если операция очень длительная (например, занимает несколько часов). Пользователь может закрыть форму или даже программу, а при получении уведомления от системы взаимодействия он увидит всплывающее окно в углу экрана, когда задача будет завершена.
Рассмотрим еще один важный нюанс, упомянутый в обсуждении. При работе фонового задания стандартный метод Сообщить() не выводит текст в окно сообщений пользователя немедленно. Все сообщения накапливаются в буфере фонового задания.
Чтобы их прочитать, при опросе состояния задания из обработчика ожидания необходимо вызвать метод ПолучитьСообщенияПользователю(Истина). Параметр Истина важен, так как он очищает прочитанные сообщения, чтобы при следующем вызове вы получили только новые порции лога. Это отличный способ реализовать текстовый лог выполнения операции в реальном времени.
Подводя итог, выберем оптимальный путь в зависимости от ваших условий:
Помните, что ключевым моментом любого решения является вынос кода из основного потока формы в фоновый процесс. Это сохраняет отзывчивость интерфейса и повышает удобство работы пользователя с программой.