Справочный материал

Длительные операции

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

Длительные операции

Приложение. Вспомогательные функции.

 

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

* Примечание: условная оценка предельной длительности серверного вызова, допустимая для распространенных браузеров и веб-серверов

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

В противном случае такие вызовы могут привести к потере работоспособности приложения:

  • из-за «зависания» браузера (как правило, браузеры предлагают прекратить выполнение скриптов на зависшей страницы или закрыть ее),
  • либо из-за аварийного завершения с ошибкой превышения установленного времени ожидания веб-сервера (или дополнительного программного обеспечения, установленного на веб-сервере).

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

  • Код, выполняющий длительную обработку данных, располагается в модуле менеджера объекта** или в общем модуле. Результат своей работы он помещает во временное хранилище;

    **Примечание: необходимо использовать процедуру-обертку в общем модуле, которая будет вызывать процедуру модуля менеджера через Выполнить. Т.к. фоновые задания могут работать только с процедурами и функциями общих модулей.
  • Для выполнения этого кода на сервере запускается фоновое задание, при этом необходимо ожидать завершения выполнения фонового задания в течении 2 сек (а в режиме медленного соединения – 4 сек);
  • Если за время ожидания выполнения задания оно не завершилось, то управление возвращается на клиент, и в клиентском коде подключается обработчик ожидания, в котором периодически проверяется состояние фонового задания. При этом интервал опроса задания увеличивается от 1 до 15 с фиксированным коэффициентом 1.4;
  • На время выполнения длительной операции пользователю отображается индикатор;
    при этом для отчетов индикатор выводится в поле табличного документа, используя свойство поля табличного документа ОтображениеСостояния:

    Отчет Формируется.

    а для прочих мест – выводится блокирующая форма (РежимОткрытияОкна = БлокироватьОкноВладельца), на которой размещена декорация с анимированной картинкой и кнопка «Отмена»:

    - Бухгалтери. и] UiJ Л М М+ М-  X  Операция выполняется...  Отмена
  • При получении от сервера информации о том, что фоновое задание завершено, полученный результат загружается из временного хранилища и обрабатывается.

2.2. Асинхронное формирование отчета требуется только для тех отчетов, которые

  • разработаны без использования СКД или с использованием СКД, но с переопределенной процедурой формирования отчета (переопределен обработчик кнопки «Сформировать» или в обработчике модуля отчета ПриКомпоновкеРезультата устанавливается СтандартнаяОбработка = Ложь).
  • и формирование которых, как правило, занимает длительное время.

Поведение таких отчетов должно быть максимально похожим на поведение отчетов на базе СКД, а именно:

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

3. Пример заполнения табличной части Реализация документа ФормированиеЗаписейКнигиПродаж.

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

Процедура ПодготовитьДанныеДляЗаполнения(ПараметрыДокумента, АдресХранилища) Экспорт
	
	ДанныеДляЗаполнения = Новый Структура;
	ДанныеДляЗаполнения.Вставить("Реализация", ПодготовитьДанныеРазделаРеализация(ПараметрыДокумента));
	ПоместитьВоВременноеХранилище(ДанныеДляЗаполнения, АдресХранилища);
	
КонецПроцедуры

В модуле формы документа располагается обработчик команды заполнения документа:

 &НаКлиенте
 Процедура ЗаполнитьДокумент(Команда)
	 ЗаданиеВыполнено = ЗаполнитьДокументНаСервере();
	 Если ЗаданиеВыполнено Тогда
		 Возврат;
	 КонецЕсли;
	 // Операция еще не завершена, выполняется с помощью фонового задания (асинхронно).
	 ПараметрыОбработчикаОжидания = Новый Структура(
	 "МинимальныйИнтервал,
	 |МаксимальныйИнтервал,
	 |ТекущийИнтервал,
	 |КоэффициентУвеличенияИнтервала", 
	 1, 15, 1, 1.4);
	 ПодключитьОбработчикОжидания("Подключаемый_ПроверитьВыполнениеЗадания", 1, Истина);
	 ФормаДлительнойОперации = ОткрытьФорму("ОбщаяФорма.ДлительнаяОперация",
	 Новый Структура("ИдентификаторЗадания", ИдентификаторЗадания), ЭтаФорма);
 КонецПроцедуры

который передает управление серверной функции ЗаполнитьДокументНаСервере, инициализирует клиентскую переменную модуля формы ПараметрыОбработчикаОжидания, подключает обработчик ожидания Подключаемый_ПроверитьВыполнениеЗадания и открывает форму-индикатор выполнения длительной операции ОбщаяФорма.ДлительнаяОперация.

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

  • Данные документа, необходимые для заполнения (работы алгоритма);
  • АдресХранилища – адрес временного хранилища, в которое фоновое задание должно поместить результат выполнения операции.
 &НаСервере
 Функция ЗаполнитьДокументНаСервере()
	 ПараметрыДокумента = Новый Структура("Дата,Организация,Реализация0", 
	 Объект.Дата, Объект.Организация, Объект.Реализация0);
	 АдресХранилища = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор);
	 ЗаданиеВыполнено = Ложь;
	 // В файловом режиме работы выполняем операцию непосредственно (синхронно).
	 Если ИнформационнаяБазаФайловая() Тогда
		 Документы.ФормированиеЗаписейКнигиПродаж.ПодготовитьДанныеДляЗаполнения(ПараметрыДокумента, АдресХранилища);
		 Возврат Истина; 
	 КонецЕсли; 
	 // В клиент-серверном режиме работы выполняем операцию в фоновом задании (асинхронно).
	 НаименованиеЗадания = НСтр("ru = 'Заполнение документа ""Формирование записей книги продаж""'");
	 ПараметрыЗаполнения = Новый Массив;
	 ПараметрыЗаполнения.Добавить(ПараметрыДокумента);
	 ПараметрыЗаполнения.Добавить(АдресХранилища);
	 Если ПолучитьСкоростьКлиентскогоСоединения() = СкоростьКлиентскогоСоединения.Низкая Тогда
		 ВремяОжидания = 4;
	 Иначе
		 ВремяОжидания = 2;
	 КонецЕсли;
	 Задание = ФоновыеЗадания.Выполнить(
	 "Документы.ФормированиеЗаписейКнигиПродаж.ПодготовитьДанныеДляЗаполнения", 
	 ПараметрыЗаполнения, , НаименованиеЗадания);
	 Попытка
		 Задание.ОжидатьЗавершения(ВремяОжидания);
	 Исключение 
		 // Специальная обработка не требуется. Предположительно, исключение вызвано истечением времени ожидания.
	 КонецПопытки;
	 ИдентификаторЗадания = Задание.УникальныйИдентификатор;
	 // Если операция уже завершилась, то сразу обрабатываем результат.
	 Если ЗаданиеВыполнено(Задание.УникальныйИдентификатор) Тогда
		 ЗаданиеВыполнено = Истина;
		 ЗагрузитьПодготовленныеДанные();
	 КонецЕсли; 
	 Возврат ЗаданиеВыполнено;
 КонецФункции 
 

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

&НаКлиенте
Процедура Подключаемый_ПроверитьВыполнениеЗадания()
	Попытка
		Если ЗаданиеВыполнено() Тогда 
			ЗагрузитьПодготовленныеДанные();
			ЗакрытьФормуДлительнойОперации();
			Возврат;
		КонецЕсли;
		
	Исключение
		ЗакрытьФормуДлительнойОперации();
		ВызватьИсключение;
	КонецПопытки;
	ПараметрыОбработчикаОжидания.ТекущийИнтервал = ПараметрыОбработчикаОжидания.ТекущийИнтервал * ПараметрыОбработчикаОжидания.КоэффициентУвеличенияИнтервала;
	Если ПараметрыОбработчикаОжидания.ТекущийИнтервал > ПараметрыОбработчикаОжидания.МаксимальныйИнтервал Тогда
		ПараметрыОбработчикаОжидания.ТекущийИнтервал = ПараметрыОбработчикаОжидания.МаксимальныйИнтервал;
	КонецЕсли;
	ПодключитьОбработчикОжидания(
	"Подключаемый_ПроверитьВыполнениеЗадания", 
	ПараметрыОбработчикаОжидания.ТекущийИнтервал, 
	Истина);
КонецПроцедуры

&НаСервере
Процедура ЗагрузитьПодготовленныеДанные()
	Результат = ПолучитьИзВременногоХранилища(АдресХранилища);
	Если ТипЗнч(СтруктураДанных) <> Тип("Структура") Тогда
		Возврат;
	КонецЕсли;
	Если СтруктураДанных.Свойство("Реализация") Тогда
		Объект.Реализация.Загрузить(СтруктураДанных.Реализация);
	КонецЕсли;
КонецПроцедуры

В приложении ниже приведен пример реализации вспомогательных функций ЗакрытьФормуДлительнойОперации, ИнформационнаяБазаФайловая и ЗаданиеВыполнено. 4. При использовании в конфигурации Библиотеки стандартных подсистем в распоряжении разработчика имеются вспомогательные функции и процедуры общих модулей ДлительныеОперации, ДлительныеОперацииКлиент, а также процедура УстановитьСостояниеПоляТабличногоДокумента общего модуля ОбщегоНазначенияКлиентСервер. Приложение. Вспомогательные функции.


&НаКлиенте
Процедура ЗакрытьФормуДлительнойОперации()
	Если ТипЗнч(ФормаДлительнойОперации) = Тип("УправляемаяФорма") Тогда
		Если ФормаДлительнойОперации.Открыта() Тогда
			ФормаДлительнойОперации.Закрыть();
		КонецЕсли;
	КонецЕсли;
КонецПроцедуры

&НаСервереБезКонтекста
Функция ИнформационнаяБазаФайловая(СтрокаСоединенияИнформационнойБазы = "") Экспорт
	Если ПустаяСтрока(СтрокаСоединенияИнформационнойБазы) Тогда
		СтрокаСоединенияИнформационнойБазы = СтрокаСоединенияИнформационнойБазы();
	КонецЕсли;
	Возврат Найти(Врег(СтрокаСоединенияИнформационнойБазы), "FILE=") = 1;
КонецФункции


Записаться по телефону