Как вывести сообщения о ходе выполнения процесса в 1С, если интерфейс зависает?

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

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

Почему 1С "зависает" и не выводит сообщения сразу?

Проанализируем архитектуру управляемого приложения. В отличие от обычных форм, где клиент и сервер часто были тесно связаны в рамках одного процесса, в управляемом приложении разделение жесткое. Когда вы вызываете процедуру с директивой &НаСервере, управление передается на сервер, а клиентский поток переходит в режим ожидания. Пока сервер не завершит выполнение всей процедуры и не вернет управление клиенту, пакет данных с накопленными сообщениями не будет передан. Именно поэтому вы видите результат работы Сообщить() только в самом конце.

Рассмотрим основные способы решения этой задачи, от стандартных механизмов БСП до современных методов с использованием Системы взаимодействия.

Решение 1: Использование механизмов БСП «Длительные операции»

Если ваша конфигурация построена на базе Библиотеки стандартных подсистем (БСП), это самый правильный и надежный путь. Механизм позволяет запустить тяжелую обработку в фоновом задании, не блокируя основной поток интерфейса. Разберем по шагам, как это работает.

Во-первых, процедура обработки данных выносится в серверный модуль и помечается как экспортная. Во-вторых, на клиенте вызывается метод БСП, который запускает эту процедуру в фоне. Проанализируем примерную схему кода:


// Код на клиенте для запуска
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияПроцедуры(УникальныйИдентификатор);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = "Обработка номенклатуры";

Результат = ДлительныеОперации.ЗапуститьПроцедуруНаСервере(
    "МойСерверныйМодуль.ОбработатьДанные", 
    ПараметрыПроцедуры, 
    ПараметрыВыполнения
);

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

Решение 2: Фоновое задание и временное хранилище (ручной метод)

Если БСП не используется, мы можем реализовать аналогичный механизм самостоятельно. Основная идея заключается в том, что клиент должен периодически "спрашивать" сервер: "Как дела?".

Рассмотрим алгоритм реализации:

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

Посмотрим на пример кода серверной части:


Процедура ОбработатьДанныеФоново(АдресХранилища) Экспорт
    Выборка = Справочники.Номенклатура.Выбрать();
    Пока Выборка.Следующий() Цикл
        // Основная работа
        Объект = Выборка.ПолучитьОбъект();
        // ... изменения ...
        Объект.Записать();
        
        // Передаем статус выполнения
        ТекстСтатуса = "Обработано: " + Объект.Наименование;
        ПоместитьВоВременноеХранилище(ТекстСтатуса, АдресХранилища);
        
        // Позволяет прервать задание администратором или системой
        ОбработкаПрерыванияПользователя();
    КонецЦикла;
КонецПроцедуры

На клиенте мы будем считывать ТекстСтатуса и выводить его в надпись на форме. Это создаст эффект "живого" интерфейса без блокировки программы. Для такой задачи также можно задействовать пример фоновых заданий с индикацией прогресса без БСП.

Решение 3: Система взаимодействия (Push-уведомления)

Это наиболее современный подход, доступный в новых версиях платформы 8.3. Выясним причину его эффективности: сервер сам может "толкнуть" сообщение клиенту, не дожидаясь запроса от него. Это избавляет от необходимости использовать обработчики ожидания.

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

Почему нельзя делать цикл на клиенте?

В обсуждении часто всплывает совет: "Запустите цикл на клиенте и вызывайте сервер для каждого объекта". Выясним, почему это плохой вариант:

Использование функции Состояние()

Важно различать Сообщить() и Состояние(). Метод Состояние() предназначен для вывода информации в строку состояния (внизу экрана) и управления индикатором прогресса (Progress Bar). Однако он работает только на стороне клиента. Если вы вызовете Состояние() на сервере, платформа попытается передать это на клиент, но опять же — только после завершения всего серверного вызова. Поэтому для визуализации прогресса лучше всего комбинировать фоновые задания и обновление элемента Индикатор на форме.

Подведем итог: для реализации отзывчивого интерфейса при длительных операциях в 1С 8.3 следует уходить от линейного выполнения кода в основном потоке. Используйте ДлительныеОперации из состава БСП или связку фоновых заданий с временным хранилищем. Это позволит вашим пользователям видеть актуальную информацию о ходе процесса, не дожидаясь "отвисания" программы.

← На главную