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

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

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

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

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

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

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

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

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


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

Вариант 2. Размещение анимированного GIF-изображения на форме

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

Рассмотрим порядок настройки элементов:

  1. Добавляем GIF-анимацию со спиннером в состав метаданных (раздел «Общие картинки») или загружаем динамически.
  2. Размещаем на управляемой форме элемент управления с видом Поле картинки, указываем путь к нашей картинке.
  3. По умолчанию устанавливаем свойство Видимость = Ложь.
  4. В момент запуска фонового процесса делаем поле видимым (Элементы.Спиннер.Видимость = Истина), а после завершения задания — скрываем его обратно.

Вариант 3. Использование поля HTML-документа с CSS/SVG анимацией

Анимированные GIF-файлы могут иметь артефакты масштабирования и проблемы с прозрачностью фона при смене темы оформления. Более гибкий и современный способ — элемент формы с видом Поле HTML документа.

Преимущества данного подхода:

  1. Идеальное масштабирование векторной SVG/CSS графики без потери качества на экранах с высоким DPI.
  2. Возможность задать полупрозрачный перекрывающий слой (overlay), который визуально затемняет элементы формы под ним.
  3. Цвет спиннера легко настраивается под стиль оформления программы через параметры стилей HTML/CSS.

Посмотрим, как инициализировать поле HTML документа кодом:


&НаСервере
Процедура ИнициализироватьСпиннер()
    
    ТекстHTML = 
    "<html><head><style>
    |body { margin: 0; background: transparent; display: flex; align-items: center; justify-content: center; height: 100vh; }
    |.loader { border: 4px solid #f3f3f3; border-top: 4px solid #005fb8; border-radius: 50%; width: 32px; height: 32px; animation: spin 1s linear infinite; }
    |@keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } }
    |</style></head><body><div class=""loader""></div></body></html>";
    
    HTMLКодСпиннера = ТекстHTML;
    
КонецПроцедуры

Вариант 4. Отдельная немодальная форма ожидания

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

Для предотвращения нежелательных действий пользователя открываем такую форму немодально с блокировкой владельца:


ПараметрыФормы = Новый Структура("ИдентификаторЗадания", ИдентификаторФоновогоЗадания);
ПараметрыОткрытия = Новый Структура;
ПараметрыОткрытия.Вставить("РежимБлокировкиОкна", РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);

ОткрытьФорму("ОбщаяФорма.ФормаОжидания", ПараметрыФормы, ЭтотОбъект, , , , , РежимОткрытияОкнаФормы.БлокироватьОкноВладельца);

Программное управление фоновым заданием без БСП

Проанализируем полный цикл отслеживания состояния фонового задания штатным функционалом платформы 1С:

  1. Запуск на сервере: метод ФоновыеЗадания.Выполнить(...) запускает процедуру в отдельном потоке. Результат помещается во временное хранилище по уникальному адресу. Клиент получает УникальныйИдентификатор задания и адрес хранилища.
  2. Запуск анимации и таймера: на клиенте включаем спиннер, блокируем кнопку запуска (Элементы.КнопкаВыполнить.Доступность = Ложь) и подключаем опрос через ПодключитьОбработчикОжидания("ПроверитьСостояниеЗадания", 1, Истина).
  3. Проверка состояния: в процедуре обработчика ожидания сервер проверяет статус объекта через ФоновыеЗадания.НайтиПоУникальномуИдентификатору(...):
    • Если Состояние равно СостояниеФоновогоЗадания.Активно — повторно подключаем обработчик ожидания.
    • Если Состояние равно СостояниеФоновогоЗадания.Завершено — выключаем спиннер, восстанавливаем доступность элементов и забираем данные через ПолучитьИзВременногоХранилища(...).
    • Если Состояние равно СостояниеФоновогоЗадания.ЗавершеноАварийно или СостояниеФоновогоЗадания.Отменено — отключаем анимацию и анализируем свойство ИнформацияОбОшибке для оповещения пользователя.

Посмотрим на пример структуры серверной функции проверки состояния:


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

Важные нюансы и ограничения

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

  1. Зависание анимации при синхронных вызовах: отрисовка GIF и CSS-анимации в тонком клиенте выполняется в основном потоке интерфейса. Если на клиенте будет выполняться тяжелый цикл или длительный контекстный вызов сервера без фонового задания, анимация спиннера полностью замрет.
  2. Защита интерфейса: одной только визуализации недостаточно. Всегда отключайте доступность ключевых кнопок на форме на время выполнения задания, чтобы исключить запуск дублирующих серверных процессов.
← На главную