В практике разработки на платформе 1С:Предприятие 8.3 часто возникает ситуация, когда перед началом длительного серверного вызова необходимо подготовить интерфейс: показать декорацию (индикатор загрузки), изменить текст надписи или видимость кнопок. Однако стандартный линейный подход «изменил свойство — вызвал сервер» часто не срабатывает. В этой статье мы подробно разберем, почему так происходит, и рассмотрим проверенные способы решения этой задачи.
Прежде чем переходить к коду, выясним причину проблемы. В тонком и толстом клиенте 1С программный код и графическая оболочка (GUI) работают в рамках одного основного потока. Когда мы пишем Элементы.ГруппаЗагрузки.Видимость = Истина;, платформа не перерисовывает форму в ту же миллисекунду. Она ставит задачу на перерисовку в очередь событий.
Если сразу после этой строки кода следует синхронный вызов серверной процедуры ВызватьСервернуюПроцедуру();, поток управления уходит на сервер и «замирает» на клиенте в ожидании ответа. Очередь событий графического интерфейса блокируется. В итоге пользователь видит изменения на форме только тогда, когда серверная процедура уже завершилась и управление вернулось в клиентский поток. Для пользователя это выглядит так, будто декорация «моргнула» в самом конце или не появилась вовсе.
Рассмотрим самый популярный и простой метод решения — использование метода ПодключитьОбработчикОжидания. Этот подход позволяет «разорвать» выполнение кода, давая платформе время на обработку графических событий в промежутке между клиентскими процедурами.
Разберем алгоритм действий по шагам:
Посмотрим на пример реализации этого метода:
&НаКлиенте
Процедура КомандаВыполнитьДействие(Команда)
// Шаг 1: Подготавливаем интерфейс
Элементы.ДекорацияСтатус.Заголовок = "Пожалуйста, подождите. Идет обработка данных...";
Элементы.ГруппаИндикатор.Видимость = Истина;
// Блокируем кнопку, чтобы избежать повторных нажатий
Элементы.КомандаВыполнитьДействие.Доступность = Ложь;
// Шаг 2: Подключаем обработчик ожидания на 0.1 сек
// Параметр "Однократно" (Истина) важен, чтобы процедура не зациклилась
ПодключитьОбработчикОжидания("ВыполнитьСервернуюОперацию", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ВыполнитьСервернуюОперацию()
// Шаг 3: Вызываем серверную процедуру
ВыполнитьДействиеНаСервере();
// Шаг 4: Возвращаем интерфейс в исходное состояние
Элементы.ГруппаИндикатор.Видимость = Ложь;
Элементы.КомандаВыполнитьДействие.Доступность = Истина;
КонецПроцедуры
Проанализируем ситуацию: если серверная операция длится более 2–5 секунд, даже с использованием обработчика ожидания клиентское приложение будет выглядеть «зависшим» во время самого вызова. Согласно стандартам разработки 1С, длительные операции должны выполняться асинхронно в фоновом режиме.
Для этого рекомендуется использовать подсистему «Длительные операции» из состава Библиотеки стандартных подсистем (БСП). Схема работы в этом случае выглядит так:
ФоновыеЗадания.Выполнить().Пример упрощенной логики запуска фонового задания:
&НаКлиенте
Процедура ЗапуститьДлительнуюОперацию()
ПараметрыЗадания = Новый Структура("Параметр1", Значение1);
РезультатЗапуска = ЗапуститьВыполнениеНаСервере(ПараметрыЗадания);
Если РезультатЗапуска.Статус = "Выполняется" Тогда
// Открываем форму ожидания БСП
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ПараметрыОжидания.ТекстСообщения = "Выполняется расчет, подождите...";
ДлительныеОперацииКлиент.ОжидатьЗавершение(РезультатЗапуска, ПараметрыОжидания,
Новый ОписаниеОповещения("ПослеЗавершенияОперации", ЭтотОбъект));
КонецЕсли;
КонецПроцедуры
Существуют и другие способы управления вниманием пользователя, которые полезно знать программисту:
Метод Состояние(). В некоторых случаях вместо манипуляций с элементами формы можно вызвать системный метод Состояние("Обработка данных...");. Он выводит небольшое окно в углу экрана. Его преимущество в том, что он часто успевает отрисоваться даже без разрыва потока через обработчик ожидания, так как реализован на более низком уровне платформы. Однако он менее выразителен для пользователя, чем яркая декорация в центре формы.
ОбновитьОтображениеДанных(). Важно понимать, что этот метод не форсирует перерисовку GUI. Он лишь заставляет элементы формы перечитать значения из связанных с ними реквизитов. Если вы изменили видимость элемента и вызвали этот метод, перерисовка всё равно произойдет только после того, как управление вернется системе. Поэтому для нашей задачи этот метод бесполезен.
Особенности веб-клиента. При разработке для браузеров использование синхронных вызовов особенно опасно. Браузер может выдать предупреждение о том, что страница не отвечает, если серверный вызов затянется. Поэтому для веб-клиента использование фоновых заданий является единственным профессиональным решением.
Выясним, какой метод выбрать:
ПодключитьОбработчикОжидания на 0.1 сек. Это просто в реализации и достаточно для большинства учетных задач.Применяя эти техники, вы сделаете свои формы «живыми» и отзывчивыми, что значительно повысит доверие пользователей к вашей программе.