Как оперативно выводить сообщения с сервера на клиент при длительной обработке в 1С

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

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

Причины эффекта накопления сообщений

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

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

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

Решение 1. Использование фоновых заданий и механизма длительных операций БСП

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

Разберем по шагам, как организовать данный процесс.

Шаг 1. Серверная процедура фонового задания

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


Процедура ПровестиПакетДокументов(Параметры, АдресРезультата) Экспорт
    МассивДокументов = Параметры.МассивДокументов;
    Всего = МассивДокументов.Количество();
    
    Для Индекс = 0 По Всего - 1 Цикл
        СсылкаНаДокумент = МассивДокументов[Индекс];
        
        // Проводим документ в отдельной транзакции
        Попытка
            ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
            ДокументОбъект.Записать(РежимЗаписиДокумента.Проведение);
            ТекстРезультата = "Успешно проведен: " + Строка(СсылкаНаДокумент);
        Исключение
            ТекстРезультата = "Ошибка проведения: " + Строка(СсылкаНаДокумент) + " (" + ОписаниеОшибки() + ")";
        КонецПопытки;
        
        Процент = Окр(((Индекс + 1) / Всего) * 100);
        
        // Передаем статус выполнения
        ДлительныеОперации.СообщитьПрогресс(Процент, ТекстРезультата);
    КонецЦикла;
КонецПроцедуры

Обратите внимание на важную особенность БСП: процедура ДлительныеОперации.СообщитьПрогресс() оптимизирована для экономии системных ресурсов и канала связи. Не рекомендуется вызывать ее слишком часто (разработчики рекомендуют интервал не чаще одного раза в 3 секунды). Если документов много и они проводятся быстро, промежуточные тексты могут склеиваться. Поэтому для больших объемов статус лучше передавать порциями (например, каждые 20 документов) или обновлять агрегированные показатели.

Шаг 2. Запуск и опрос на стороне клиента

На клиенте запускаем фоновое задание через ДлительныеОперации.ВыполнитьВФоне() и настраиваем обработчик ожидания:


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

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

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

Решение 2. Пошаговая (порционная) обработка с клиента

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

Разберем логику работы:

  1. Клиент формирует полный список идентификаторов документов, которые предстоит обработать.
  2. Список разбивается на небольшие пачки (например, по 20–50 штук).
  3. Клиент вызывает короткую серверную процедуру для обработки только текущей порции.
  4. Сервер проводит пачку и немедленно возвращает результат клиенту.
  5. Клиент выводит отчет о проведенных документах в интерфейс, обновляет индикатор и через ПодключитьОбработчикОжидания() или асинхронный цикл инициирует серверный вызов для следующей порции.

Посмотрим на пример клиентского цикла:


&НаКлиенте
Асинхронная Процедура ЗапуститьПошаговуюОбработку()
    ВсегоДокументов = СписокСсылок.Количество();
    РазмерПорции = 20;
    ТекущийИндекс = 0;
    
    Пока ТекущийИндекс < ВсегоДокументов Цикл
        // Формируем срез для текущей порции
        Порция = ПолучитьПорцию(ТекущийИндекс, РазмерПорции);
        
        // Серверный вызов на короткое время
        РезультатыПорции = ОбработатьПорциюНаСервере(Порция);
        
        Для Каждого СтрРезультат Из РезультатыПорции Цикл
            Сообщить(СтрРезультат);
        КонецЦикла;
        
        ТекущийИндекс = ТекущийИндекс + РазмерПорции;
        
        // Делаем минимальную паузу, чтобы интерфейс успел отрисовать сообщения
        Ждать ТекущийИндекс;
    КонецЦикла;
    
    Сообщить("Обработка всех документов полностью завершена.");
КонецПроцедуры

Преимущества и недостатки подхода: такой способ предельно прост в отладке и не требует настройки фоновых заданий. Однако увеличивается общее количество клиент-серверных вызовов, что при медленном сетевом соединении между клиентом и сервером 1С может несколько увеличить суммарное время работы.

Решение 3. Использование push-механизма Системы взаимодействия

В современных версиях платформы 1С для мгновенной доставки сообщений с сервера на клиент без использования регулярных таймеров опроса можно применять Систему взаимодействия.

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

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

Данный вариант обеспечивает максимальную оперативность, однако требует, чтобы в информационной базе была предварительно подключена и настроена Система взаимодействия.

Итоги

Для реализации оперативного вывода сообщений при длительных операциях выбирайте инструмент под ваши задачи:

  1. Фоновые задания и подсистема «Длительные операции» БСП — стандартное, наиболее правильное и надежное решение для подавляющего большинства типовых и нетиповых конфигураций.
  2. Порционная обработка на клиенте — простой альтернативный способ, когда необходимо избежать работы с фоновыми потоками.
  3. Система взаимодействия — современный вариант для моментальной доставки событий без периодического опроса.
← На главную