Каждый разработчик 1С рано или поздно сталкивается с ситуацией, когда при выполнении длительного цикла на клиенте вызванные методы Сообщить() не выводят текст немедленно. Вместо этого пользователь видит «песочные часы» или вращающийся кружок ожидания, а вся пачка сообщений «вываливается» в окно сообщений только после полного завершения обработки. Рассмотрим подробнее, почему это происходит и какими способами можно заставить интерфейс 1С быть более отзывчивым.
Разберем внутреннюю механику работы платформы «1С:Предприятие 8». Основная причина задержки кроется в архитектуре клиентского приложения. В управляемом приложении поток графического интерфейса (GUI) и поток выполнения программного кода на языке 1С — это, по сути, один и тот же поток.
Проанализируем ситуацию: когда вы запускаете тяжелый цикл Для сч = 0 По 10000 Цикл, процессор полностью занят вычислениями встроенного языка. Поскольку поток один, у платформы просто не остается ресурсов на то, чтобы перерисовать окно сообщений или обновить форму. Метод Сообщить() в данном случае не выводит текст на экран мгновенно, а помещает его в специальный буфер (массив накопления). Этот буфер «сбрасывается» на экран только в тот момент, когда выполнение кода завершается и управление возвращается платформе для обновления интерфейса.
Важный нюанс: такая оптимизация сделана разработчиками 1С намеренно. Если бы система пыталась перерисовывать окно сообщений на каждой итерации быстрого цикла, производительность приложения упала бы в десятки раз из-за постоянных затрат на отрисовку графики.
Если нам нужно просто информировать пользователя о ходе процесса (например, «Обработано 500 из 1000 строк»), самым простым и эффективным способом будет использование метода Состояние(). В отличие от окна сообщений, панель состояния (строка внизу экрана или отдельное окно прогресса) обновляется платформой более приоритетно.
Рассмотрим пример кода:
Для Счетчик = 1 По ОбщееКоличество Цикл
// Какая-то полезная нагрузка
Процент = Окр(Счетчик / ОбщееКоличество * 100);
Состояние("Выполняется обработка данных...", Процент, "Подождите завершения...");
КонецЦикла;
Преимущество этого метода: он визуально отделен от основной формы и не требует завершения работы процедуры для обновления индикатора прогресса. Однако у него есть минус — история сообщений не сохраняется, пользователь видит только текущий статус.
Как было замечено в ходе обсуждения на форуме, существует отличный лайфхак для создания интерактивного лога в реальном времени. Если мы не можем заставить стандартное окно сообщений обновляться, мы можем создать свое собственное прямо на форме.
Разберем по шагам, как это реализовать:
ТекстЛога и типом Строка (неограниченной длины).Пример реализации:
&НаКлиенте
Процедура ВыполнитьДлительнуюОперацию()
ТекстЛога = "Начало обработки..." + Символы.ПС;
Для сч = 1 По 100 Цикл
// Имитация работы
ТекстЛога = ТекстЛога + "Обработка итерации №" + Строка(сч) + Символы.ПС;
// Магия обновления интерфейса
ЭтаФорма.ОбновитьОтображениеДанных();
КонецЦикла;
ТекстЛога = ТекстЛога + "Завершено!";
КонецПроцедуры
При использовании Поля текстового документа и метода ОбновитьОтображениеДанных(), текст будет появляться в поле синхронно с ходом цикла, что решает проблему «замирания» интерфейса.
Еще один вариант — выводить всплывающие окна («тосты»), которые появляются в углу экрана. Метод ПоказатьОповещениеПользователя() работает асинхронно и не блокирует выполнение кода.
Однако стоит помнить о здравом смысле: если вызвать этот метод 1000 раз в секунду, интерфейс пользователя превратится в хаос, а система может начать тормозить. Этот метод хорош для ключевых этапов (например, «Загрузка файла завершена», «Найдена критическая ошибка»).
Это наиболее профессиональный подход с точки зрения проектирования интерфейсов. Суть заключается в том, чтобы не выполнять весь цикл целиком, а разбить его на «кванты» времени. Мы выполняем, например, 50 итераций, после чего прерываемся и даем платформе «вдохнуть» (обновить интерфейс), а затем запускаем следующую порцию через 0.1 секунды.
Проанализируем примерную схему:
ПодключитьОбработчикОжидания("ИмяПроцедуры", 0.1, Истина).В моменты этих микро-пауз платформа успеет вывести все накопленные сообщения Сообщить() на экран, и пользователь будет видеть прогресс в реальном времени.
В современных конфигурациях (ЕРП, УТ 11, БСП) крайне не рекомендуется выполнять тяжелые вычисления непосредственно в клиентском потоке. Правильный путь — запуск фонового задания на сервере.
Выясним, как это работает в типовых решениях:
ДлительныеОперации.ЗапуститьВыполнениеНаСервере().Сообщить(), а сохраняет их в специальное временное хранилище или использует методы БСП для передачи статуса.Мы выяснили, что «зависание» сообщений — это не баг, а особенность однопоточной архитектуры клиента 1С. Для решения проблемы мы можем:
Состояние() для простых индикаторов.Поле текстового документа на форме для детального отчета.Выбор конкретного метода зависит от сложности вашей задачи, но теперь вы знаете, как сделать работу пользователя с вашими обработками комфортной и информативной.