Как реализовать событие после первого показа формы в 1С для выполнения тяжелых расчетов?

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

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

В этой статье мы подробно проанализируем, как обойти это ограничение в Обычных формах (ОФ), создав эффект «отложенного старта», когда форма сначала показывается пользователю с надписью «Загрузка...», а затем начинает выполнять тяжелую работу.

Причина проблемы: Особенности жизненного цикла формы

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

Решение №1: Использование обработчика ожидания (Имитация события «ПослеОткрытия»)

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

Рассмотрим по шагам, как это реализовать:

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

Проанализируем пример кода:


Процедура ПриОткрытии()
    // Делаем основную панель с данными невидимой, если нужно
    ЭлементыФормы.ОсновнаяПанель.Видимость = Ложь;
    
    // Показываем надпись о загрузке
    ЭлементыФормы.НадписьИнфо.Видимость = Истина;
    
    // Подключаем процедуру расчета. 
    // Интервал 0.1 секунды достаточен для отрисовки формы.
    ПодключитьОбработчикОжидания("ВыполнитьДлительныйРасчет", 0.1, Истина);
КонецПроцедуры

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

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

Решение №2: Использование фоновых заданий (Для клиент-серверного варианта)

Если база работает в клиент-серверном режиме на платформе 8.2 или 8.3, мы можем пойти еще дальше и вынести расчет на сервер в фоновом режиме. Это позволит интерфейсу оставаться полностью «живым» — пользователь сможет даже передвигать форму или нажимать другие кнопки, пока идет расчет.

Выясним, как организовать мониторинг фонового задания в Обычных формах:

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

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


Перем ИдентификаторЗадания;

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

Процедура ПроверитьСтатусЗадания()
    Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
    
    Если Задание.Состояние = СостояниеФоновогоЗадания.Завершено Тогда
        ОтключитьОбработчикОжидания("ПроверитьСтатусЗадания");
        // Получаем результат и обновляем форму
        ОбработатьРезультат(Задание.ПолучитьСообщенияПользователю());
    ИначеЕсли Задание.Состояние = СостояниеФоновогоЗадания.АварийноЗавершено Тогда
        ОтключитьОбработчикОжидания("ПроверитьСтатусЗадания");
        Предупреждение("Произошла ошибка при расчете на сервере.");
    КонецЕсли;
КонецПроцедуры

Важный нюанс: Фоновые задания в Обычных формах требуют тщательной проработки механизма передачи данных обратно в форму (через временное хранилище или записи в базе данных), так как прямого доступа к объекту ЭтаФорма из фонового задания нет.

Решение №3: Метод принудительной перерисовки (Обновить)

Иногда программисты пытаются использовать метод ЭтаФорма.Обновить() или ЭлементыФормы.ИмяЭлемента.Обновить() непосредственно в теле процедуры ПриОткрытии. Посмотрим на этот подход критически.

Код может выглядеть так:


Процедура ПриОткрытии()
    НадписьСтатус = "Подключение к базе...";
    ЭтаФорма.Обновить(); // Попытка заставить Windows отрисовать изменения
    
    // Тяжелый запрос
    Результат = ВыполнитьЗапрос();
КонецПроцедуры

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

Практические советы по работе с «нервными» пользователями

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

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

← На главную