Разберем распространенную проблему разработки в 1С: при выполнении длительного алгоритма на сервере требуется отображать пользователю прогресс или статус каждого пройденного этапа. Однако, если попытаться менять значения реквизитов формы или текстовых надписей непосредственно внутри контекстной серверной процедуры, пользователь не увидит никаких изменений в процессе работы. Все обновления интерфейса отобразятся на экране одновременно лишь после завершения работы серверной процедуры и возврата управления на клиент.
Проанализируем, почему платформа 1С так себя ведет. При прямом вызове серверной процедуры с клиента клиентское приложение и сервер приложений работают по строгой схеме «запрос-ответ»:
Поскольку в процессе выполнения серверного кода связь с клиентом не поддерживается, перерисовка интерфейса в середине работы процедур невозможно. Для решения этой задачи требуется выходить из контекста единого серверного вызова.
Посмотрим на самое простое решение задачи: вынесем логику каждого этапа в отдельную серверную процедуру, а управление последовательностью выполнения перенесем на клиентскую сторону.
При таком подходе клиент делает вызов первого этапа, получает результат, обновляет надпись на форме, затем вызывает следующий этап. Для того чтобы платформа успевала перерисовать элементы формы между вызовами, можно использовать подключение обработчика ожидания.
Рассмотрим пример кода на клиенте:
&НаКлиенте
Процедура ЗапуститьОбработкуПоЭтапам()
// Выполняем Этап 1
РезультатЭтапа1 = ВыполнитьЭтап1НаСервере();
Элементы.НадписьСтатус.Заголовок = "Этап 1 завершен: " + РезультатЭтапа1;
// Подключаем обработчик ожидания для перехода к следующему этапу,
// чтобы интерфейс гарантированно успел обновиться
ПодключитьОбработчикОжидания("ЗапуститьЭтап2", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ЗапуститьЭтап2()
РезультатЭтапа2 = ВыполнитьЭтап2НаСервере();
Элементы.НадписьСтатус.Заголовок = "Этап 2 завершен: " + РезультатЭтапа2;
КонецПроцедуры
Если серверный процесс длительный и нежелательно блокировать интерфейс или разбивать логику на множество мелких клиентских процедур, оптимальным решением является запуск фонового задания.
В конфигурациях, использующих Библиотеку стандартных подсистем (БСП), для этого предназначены механизмы подсистемы ДлительныеОперации:
ДлительныеОперации.СообщитьПрогресс(Процент, Текст).
// Код внутри процедуры фонового задания
ДлительныеОперации.СообщитьПрогресс(25, "Этап 1 успешно выполнен");
// Выполнение логики этапа 2...
ДлительныеОперации.СообщитьПрогресс(50, "Этап 2 успешно выполнен");
ДлительныеОперацииКлиент.ЗапуститьДлительнуюОперацию(). Для считывания статуса на клиенте подключается опрос фонового задания через ДлительныеОперации.ПрочитатьПрогресс() или стандартное окно ожидания.Рассмотрим еще один метод взаимодействия фонового задания с формой без использования БСП. Внутри фонового задания вызовы процедуры Сообщить() накапливаются в специальной очереди сообщений фонового задания.
На форме через ПодключитьОбработчикОжидания с интервалом в 1–2 секунды вызывается функция ПолучитьСообщенияПользователю(Истина), передавая идентификатор фонового задания. Параметр Истина очищает очередь и возвращает массив сообщений, которые выводились фоновым заданием на каждом этапе.
Разберем пример кода опроса сообщений на клиенте:
&НаКлиенте
Процедура ПроверитьХодВыполнения()
// Получаем накапливаемые сообщения фонового задания
МассивСообщений = ПолучитьСообщенияПользователю(Истина);
Для Каждого Сообщение Из МассивСообщений Цикл
Элементы.НадписьСтатус.Заголовок = Сообщение.Текст;
КонецЦикла;
КонецПроцедуры
Проанализируем ключевые особенности, которые необходимо учитывать при реализации:
НачатьТранзакцию() и ЗафиксироватьТранзакцию()), промежуточные данные в базе (например, записи в регистрах или справочниках) будут недоступны для чтения другим сеансам до момента завершения транзакции.ПодключитьОбработчикОжидания на клиенте задавайте интервал опроса не менее 1 секунды, чтобы избежать избыточной нагрузки на сервер приложений.