Отображение состояния в обычных и управляемых формах

Источник: http://курсы-по-1с.рф/articles/2017-09-08-display-progress-of-long-operations/

Обычные формы

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

В обычном режиме клиентский сеанс открывает постоянное соединение с базой данных, а выполнение программного кода на встроенном языке преимущественно происходит на стороне клиента. В связи с этим в любой строчке кода, описывающего длительный процесс, можно оценить объем обработанных данных, получить процент его выполнения и поместить полученное значение в реквизит формы, связанный с выведенным на форму элементом «Индикатор». В этот момент пользователь увидит графическое изменение отображения полосы индикатора в интерфейсе – опять же, благодаря тому, что всё действие происходит на клиенте. Самый простой «длительный процесс» с выводом процента выполнения в обычном режиме может выглядеть следующим образом:

Процедура КнопкаВыполнитьНажатие(Кнопка)

КоличествоОбходов = 100500; Для Инд = 0 По КоличествоОбходов Цикл

//такая вот нехитрая эмуляция длительной операции

Индикатор = Инд*100/КоличествоОбходов;

КонецЦикла;

КонецПроцедуры

Рисунок 2. Обычные формы – пример длительной операции с выводом процента выполнения в индикатор

Как говорится – «проще не придумаешь».

Никакого «лишнего» кода, всё максимально прозрачно, понятно и самое главное – работает! На этом моменте кто-то из читателей ностальгично вздохнёт, так как мы переходим к следующей части статьи – к управляемым формам

Управляемые формы

С приходом платформы 8.2 и управляемых форм ситуация с индикатором в корне изменилась. Но дело совсем не в версии платформы и не в новых формах, а в появлении новых видов клиентов для «1С:Предприятие» – тонкого и web-клиента.

Если провести сравнение с обычным режимом, то сразу бросаются следующие отличия:

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

  • Отсутствует постоянное соединение клиентской части с серверной

  • Встроенный язык разделён на клиентский и серверный.

Есть ещё один важный, но не отображённый на схеме нюанс – серверный вызов, посредством которого происходит взаимодействие клиентской части и серверной. Он может быть инициирован только клиентом. А это значит, что со стороны сервера отправить данные на сторону клиента можно только в том случае, если с соответствующего клиентского сеанса пришёл запрос.

Как всё это повлияло на использование индикатора для отображения информации о ходе выполнения длительного процесса? Давайте подробно в этом разберёмся.

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

Получается, что в том или ином виде всегда требуется доступ к базе данных и/или выполнение методов, доступных только на стороне сервера. Для этого на него необходимо передать управление.

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

Получается, что если взять код из предыдущего примера и просто разбить его на клиентскую и серверную часть, то получим долгое подвисание приложения, после чего индикатор резко установится в значение «100%».

&НаСервере

Процедура КомандаВыполнитьНажатиеНаСервере()

КоличествоОбходов = 100500;

Для Инд = 0 По КоличествоОбходов Цикл

//такая вот нехитрая эмуляция длительной операции

Индикатор = Инд*100/КоличествоОбходов;

КонецЦикла;

КонецПроцедуры

&НаКлиенте

Процедура КомандаВыполнитьНажатие(Команда)

КомандаВыполнитьНажатиеНаСервере();

КонецПроцедуры

Рисунок 4. Попытка использовать код из обычного режима в управляемом

При таком использовании индикатора от него пользы никакой нет. Поэтому разработчики идут на различные хитрости – выполняют длительные процессы «порционно» с отображением на полосе индикатора значений относительно «порций»; используют динамическое уменьшение скорости движения индикатора в зависимости от времени выполнения процесса; или придумывают другие варианты. Но ни один из них не имеет ничего общего с отображением выполнения конкретного процесса в режиме реального времени.

Именно поэтому при обновлении типовых конфигураций рядом с индикатором мы наблюдаем фразу примерно следующего содержания: «эта операция может занять длительное время – от нескольких минут до нескольких часов». И отчасти поэтому при формировании отчётов крутятся «безликие» круги-индикаторы, которые в виде простой анимации указывают на то, что программа вовсе не зависла.

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

  1. Длительная операция запускается в виде фонового задания, в ходе выполнения которого промежуточные результаты помещаются во временное хранилище.

  2. На стороне клиента запускается обработчик ожидания, который с определённой периодичностью опрашивает временное хранилище и выводит данные из него в полосу индикатора.

Программный код будет состоять из двух частей: из кода интерфейсной части (в нашем случае – обработки) и кода общего модуля. Модуль формы обработки будет выглядеть примерно так:

&НаКлиенте

Процедура КомандаВыполнитьНажатие(Команда) //стартуем выполнение длительной операции на сервере в фоновом задании

КомандаВыполнитьНажатиеНаСервере(); //подключаем обработчик ожидания для мониторинга выполнения процесса

ПодключитьОбработчикОжидания("ОбработчикОжидания",5,Истина);

КонецПроцедуры

&НаСервере

Процедура КомандаВыполнитьНажатиеНаСервере()

АдресХранилища = ПоместитьВоВременноеХранилище( Новый Структура("Инд,КоличествоОбходов",0,1),ЭтаФорма.УникальныйИдентификатор);

МассивПараметров = Новый Массив; МассивПараметров.Добавить(АдресХранилища);

ФЗ = ФоновыеЗадания.Выполнить("ОбщийМодуль1.ФоновыйПроцесс",МассивПараметров);

КонецПроцедуры

&НаКлиенте

Процедура ОбработчикОжидания() Экспорт

ДанныеОВыполнении = ПолучитьИзВременногоХранилища(АдресХранилища);

Если ТипЗнч(ДанныеОВыполнении) = Тип("Структура") Тогда

Индикатор = ДанныеОВыполнении.Инд*100/ДанныеОВыполнении.КоличествоОбходов;

Если ДанныеОВыполнении.Инд <> ДанныеОВыполнении.КоличествоОбходов Тогда

ПодключитьОбработчикОжидания("ОбработчикОжидания",5,Истина);

КонецЕсли;

КонецЕсли;

КонецПроцедуры

Рисунок 5. Управляемые формы – пример длительной операции с выводом процента выполнения в индикатор. Модуль формы обработки

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

//Фоновое задание для УправляемыеФормы_Вариант2

Процедура ФоновыйПроцесс(Адрес) Экспорт

КоличествоОбходов = 100500;

Для Инд = 0 По КоличествоОбходов Цикл //такая вот нехитрая эмуляция длительной операции

ПоместитьВоВременноеХранилище( Новый Структура("Инд,КоличествоОбходов", Инд,КоличествоОбходов), Адрес);

КонецЦикла;

КонецПроцедуры

Рисунок 6. Управляемые формы – пример длительной операции с выводом процента выполнения в индикатор. Общий модуль

Для тех, кто захочет проверить работоспособность данного примера, дополнительно приведём скриншот формы обработки:

Рисунок 7. Управляемые формы – пример длительной операции с выводом процента выполнения в индикатор. Форма обработки

Несмотря на то, что индикатор будет «живым», сказать, что эффект достигнут и пример рабочий, на сто процентов нельзя. Потому что между реальным состоянием выполнения процесса и интерфейсом пользователя есть аж целых две «прослойки» – временное хранилище и обработчик ожидания. При таком подходе мало того, что отображение идёт не в режиме реального времени, так ещё и возрастает возможность возникновения различного вида сбоев из-за использования промежуточных звеньев.

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