В обычном приложении отображение прогресса не вызывало сложностей: код выполнялся в едином потоке, и разработчик мог напрямую обращаться к элементам формы или вызывать перерисовку интерфейса. В управляемом приложении действует строгая клиент-серверная архитектура. Когда управление передается на сервер, клиентский интерфейс блокируется и «замирает» до окончания серверного вызова, из-за чего обновить индикатор на форме напрямую из серверного контекста невозможно.
Разберем по шагам основные архитектурные подходы и практические методы создания шкалы прогресса в управляемых формах 1С:Предприятие.
Если разработка ведется в типовой или доработанной конфигурации, содержащей Библиотеку стандартных подсистем (БСП), ручная работа с потоками и таймерами не требуется. В БСП встроен специальный механизм, берущий на себя запуск фонового задания, сбор процента выполнения и отображение типового диалогового окна с индикатором.
Рассмотрим порядок реализации длительного алгоритма с помощью БСП:
ДлительныеОперации.СообщитьПрогресс().ДлительныеОперации.ЗапуститьВыполнениеВФоне().ДлительныеОперацииКлиент.Посмотрим на пример серверной процедуры длительного расчета:
Процедура ВыполнитьОбработкуНаСервере(ПараметрыВыполнения, АдресРезультата) Экспорт
МассивДанных = ПараметрыВыполнения.ДанныеДляОбработки;
ВсегоЭлементов = МассивДанных.Количество();
Для Индекс = 0 По ВсегоЭлементов - 1 Цикл
// Выполняем полезное действие над элементом
ОбработатьЭлемент(МассивДанных[Индекс]);
// Вычисляем процент выполнения
Процент = Окр(((Индекс + 1) / ВсегоЭлементов) * 100);
// Передаем статус в механизм БСП
ТекстСообщения = СтрШаблон("Обработано %1 из %2 строк", Индекс + 1, ВсегоЭлементов);
ДлительныеОперации.СообщитьПрогресс(Процент, ТекстСообщения);
КонецЦикла;
КонецПроцедуры
Если конфигурация разрабатывается с нуля или БСП не используется, мы можем организовать параллельное выполнение через платформенный механизм фоновых заданий и опрос состояния по таймеру.
Проанализируем алгоритм взаимодействия клиента и сервера:
ФоновыеЗадания.Выполнить().СообщениеПользователю со специальной структурой данных.ПодключитьОбработчикОжидания(), который с интервалом в 1–2 секунды запрашивает статус фонового задания и значение прогресса, обновляя элемент формы.ОтключитьОбработчикОжидания().Посмотрим на пример реализации клиентского опроса состояния:
&НаКлиенте
Процедура ЗапуститьПроцесс(Команда)
ИдентификаторЗадания = ЗапуститьЗаданиеНаСервере();
ПодключитьОбработчикОжидания("ПроверитьСтатусЗадания", 1);
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьСтатусЗадания()
РезультатПроверки = ПроверитьПрогрессНаСервере(ИдентификаторЗадания);
// Обновляем реквизит формы, связанный с Полем индикатора
ПрогрессВыполнения = РезультатПроверки.Процент;
Если РезультатПроверки.Завершено Тогда
ОтключитьОбработчикОжидания("ПроверитьСтатусЗадания");
ПоказатьОповещениеПользователя("Успех", , "Обработка успешно завершена!");
КонецЕсли;
КонецПроцедуры
Когда операция не требует выполнения в отдельном потоке фонового задания, можно использовать порционный подход. Задача разбивается на пачки элементов (например, по 100–500 записей).
Рассмотрим схему работы:
ПодключитьОбработчикОжидания() с нулевой или минимальной задержкой запускает обработку следующей пачки.Такой подход обеспечивает интерактивность: интерфейс не зависает, индикатор плавно заполняется, а пользователь сохраняет возможность нажать кнопку отмены между порциями.
Если длительный процесс происходит непосредственно на клиенте (например, разбор локального файла Microsoft Excel или выгрузка данных через COM-соединение), доступен стандартный метод платформы Состояние().
Разберем пример его применения в цикле:
&НаКлиенте
Процедура ПрочитатьФайлНаКлиенте()
ВсегоСтрок = ТаблицаФайла.Количество();
Для НомерСтроки = 1 По ВсегоСтрок Цикл
// Обработка строки файла
ОбработатьСтрокуКлиент(НомерСтроки);
Процент = Окр((НомерСтроки / ВсегоСтрок) * 100);
Состояние("Обработка файла данных...", Процент, "Прервать работу: Ctrl + Break");
КонецЦикла;
КонецПроцедуры
Для наглядного отображения прогресса в управляемой форме применяются следующие элементы:
ПрогрессВыполнения), перетащите его в элементы формы и выберите вид Поле индикатора. Настройте свойства МинимальноеЗначение = 0, МаксимальноеЗначение = 100 и включите флаг ОтображатьЗначение.