Как отображать этапы выполнения серверной процедуры на управляемой форме в 1С?

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

Разберем распространенную проблему разработки в 1С: при выполнении длительного алгоритма на сервере требуется отображать пользователю прогресс или статус каждого пройденного этапа. Однако, если попытаться менять значения реквизитов формы или текстовых надписей непосредственно внутри контекстной серверной процедуры, пользователь не увидит никаких изменений в процессе работы. Все обновления интерфейса отобразятся на экране одновременно лишь после завершения работы серверной процедуры и возврата управления на клиент.

Выясним причину платформенного поведения

Проанализируем, почему платформа 1С так себя ведет. При прямом вызове серверной процедуры с клиента клиентское приложение и сервер приложений работают по строгой схеме «запрос-ответ»:

  1. Клиентский сеанс отправляет запрос на сервер и переходит в состояние ожидания.
  2. Серверная процедура последовательно выполняет весь переданный код. Все изменения реквизитов и элементов формы фиксируются только в контексте сервера.
  3. По окончании работы сервер формирует единый пакет ответа с обновленным контекстом формы и отправляет его обратно на клиент.
  4. Клиентское приложение получает ответ и перерисовывает управляемую форму.

Поскольку в процессе выполнения серверного кода связь с клиентом не поддерживается, перерисовка интерфейса в середине работы процедур невозможно. Для решения этой задачи требуется выходить из контекста единого серверного вызова.

Способ 1. Разбиение процесса на пошаговые клиентские вызовы

Посмотрим на самое простое решение задачи: вынесем логику каждого этапа в отдельную серверную процедуру, а управление последовательностью выполнения перенесем на клиентскую сторону.

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

Рассмотрим пример кода на клиенте:


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

&НаКлиенте
Процедура ЗапуститьЭтап2()
    
    РезультатЭтапа2 = ВыполнитьЭтап2НаСервере();
    Элементы.НадписьСтатус.Заголовок = "Этап 2 завершен: " + РезультатЭтапа2;
    
КонецПроцедуры

Способ 2. Использование фонового задания и подсистемы «Длительные операции» БСП

Если серверный процесс длительный и нежелательно блокировать интерфейс или разбивать логику на множество мелких клиентских процедур, оптимальным решением является запуск фонового задания.

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

  1. На сервере в фоновом задании: для передачи статуса и процента выполнения используется процедура ДлительныеОперации.СообщитьПрогресс(Процент, Текст).
    
    // Код внутри процедуры фонового задания
    ДлительныеОперации.СообщитьПрогресс(25, "Этап 1 успешно выполнен");
    // Выполнение логики этапа 2...
    ДлительныеОперации.СообщитьПрогресс(50, "Этап 2 успешно выполнен");
    
  2. На клиенте: операция запускается с помощью ДлительныеОперацииКлиент.ЗапуститьДлительнуюОперацию(). Для считывания статуса на клиенте подключается опрос фонового задания через ДлительныеОперации.ПрочитатьПрогресс() или стандартное окно ожидания.

Способ 3. Мониторинг сообщений пользователю из фонового задания

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

На форме через ПодключитьОбработчикОжидания с интервалом в 1–2 секунды вызывается функция ПолучитьСообщенияПользователю(Истина), передавая идентификатор фонового задания. Параметр Истина очищает очередь и возвращает массив сообщений, которые выводились фоновым заданием на каждом этапе.

Разберем пример кода опроса сообщений на клиенте:


&НаКлиенте
Процедура ПроверитьХодВыполнения()
    
    // Получаем накапливаемые сообщения фонового задания
    МассивСообщений = ПолучитьСообщенияПользователю(Истина);
    Для Каждого Сообщение Из МассивСообщений Цикл
        Элементы.НадписьСтатус.Заголовок = Сообщение.Текст;
    КонецЦикла;
    
КонецПроцедуры

Ограничения и важные нюансы

Проанализируем ключевые особенности, которые необходимо учитывать при реализации:

← На главную