358 документов
← К списку

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

страница

#std642

Область применения: управляемое приложение.

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

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

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

  • браузер может предложить прекратить длительно выполняющийся сценарий, после чего приложение станет неработоспособным;
  • веб сервер может прервать длительное обращение к серверу 1С:Предприятия и вернуть ошибку 504 (шлюз не отвечает);
  • в случае длительного выполнения операции, у пользователя нет возможности отменить ее.

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

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

    *Примечание: необходимо использовать процедуру-обертку в общем модуле, которая будет вызывать процедуру модуля менеджера через ОбщегоНазначения.ВыполнитьМетодКонфигурации. Т.к. фоновые задания могут работать только с процедурами и функциями общих модулей.

  • Для выполнения этого кода на сервере запускается фоновое задание, при этом необходимо ожидать завершения выполнения фонового задания в течение 0.8 сек;

  • Если за время ожидания выполнения задания оно не завершилось, то управление возвращается на клиент, и в клиентском коде подключается обработчик ожидания, в котором периодически проверяется состояние фонового задания. При этом интервал опроса задания увеличивается от 1 до 15 секунд с фиксированным коэффициентом 1.4;

  • На время выполнения длительной операции пользователю отображается индикатор; при этом для отчетов индикатор выводится в поле табличного документа, используя свойство поля табличного документа ОтображениеСостояния:

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

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

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

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

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

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

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

Пример выполнения функции в фоновом задании при использовании в конфигурации Библиотеки стандартных подсистем. В модуле менеджера объекта размещена функция, которая выполняет поиск настроек и возвращает их:

Функция ОпределитьНастройкиУчетнойЗаписи(АдресЭлектроннойПочты, Пароль) Экспорт
  ...
  Возврат Настройки;
КонецФункции

В форме объекта выполняется вызов этой функции в фоновом задании в три этапа:

  1. запуск фонового задания на сервере,
  2. подключение обработчика завершения фонового задания на клиенте,
  3. обработка результата выполнения фонового задания.

&НаКлиенте
Процедура НастроитьПараметрыПодключенияАвтоматически()

  // 1. Запуск фонового задания на сервере.
  ДлительнаяОперация = НачатьПоискНастроекУчетнойЗаписи();

  // 2. Подключение обработчика завершения фонового задания.
  ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
  Оповещение = Новый ОписаниеОповещения("ПриЗавершенииПоискаНастроек", ЭтотОбъект);
  ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, Оповещение, ПараметрыОжидания);

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

&НаСервере
Функция НачатьПоискНастроекУчетнойЗаписи()

  ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияФункции(УникальныйИдентификатор);
  Возврат ДлительныеОперации.ВыполнитьФункцию(ПараметрыВыполнения,
"Справочники.УчетныеЗаписиЭлектроннойПочты.ОпределитьНастройкиУчетнойЗаписи",
АдресЭлектроннойПочты, Пароль);

КонецФункции

// 3. Обработка результата выполнения фонового задания.

// Параметры:
// Результат - см. ДлительныеОперацииКлиент.НовыйРезультатДлительнойОперации
// ДополнительныеПараметры - Неопределено
//
&НаКлиенте
Процедура ПриЗавершенииПоискаНастроек(Результат, ДополнительныеПараметры) Экспорт

  Если Результат = Неопределено Тогда // Пользователь отменил задание.
    Возврат;
  КонецЕсли;

  Если Результат.Статус = "Ошибка" Тогда
    СтандартныеПодсистемыКлиент.ВывестиИнформациюОбОшибке(Результат.ИнформацияОбОшибке);
    Возврат;
  КонецЕсли;

  Настройки = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
  УдалитьИзВременногоХранилища(Результат.АдресРезультата);
  УстановитьНастройкиУчетнойЗаписи(Настройки);

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

Методическая рекомендация (полезный совет)

3.1. При каждом выполнении фонового задания его результат помещается во временное хранилище на время жизни формы:

ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияФункции(УникальныйИдентификатор);
ДлительныеОперации.ВыполнитьФункцию(ПараметрыВыполнения, ПараметрФоновогоЗадания);

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

Настройки = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
УдалитьИзВременногоХранилища(Результат.АдресРезультата); // Данные во временном хранилище больше не требуются.

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

&НаСервере
Процедура ПриСозданииНаСервере(Отказ)
  АдресРезультатаФоновогоЗадания = ПоместитьВоВременноеХранилище(Неопределено, УникальныйИдентификатор); // Резервируем адрес временного хранилища
КонецПроцедуры

&НаСервере
Функция НачатьПоискНастроекУчетнойЗаписи()
  ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияФункции(УникальныйИдентификатор);
  ПараметрыВыполнения.АдресРезультата = АдресРезультатаФоновогоЗадания; // всегда используем одно и то же временное хранилище

  Возврат ДлительныеОперации.ВыполнитьФункцию(ПараметрыВыполнения,
"Справочники.УчетныеЗаписиЭлектроннойПочты.ОпределитьНастройкиУчетнойЗаписи", АдресЭлектроннойПочты, Пароль);
КонецФункции

4. Если в конфигурации реализуются алгоритмы, инициирующие запуск фоновых заданий или запись данных информационной базы без участия пользователя (например, регулярное обновление информации в открытой форме), то в них следует проверять, что в текущем сеансе не установлен монопольный режим. В противном случае, следует блокировать попытки выполнения таких действий. Например:

Если МонопольныйРежим() Тогда
  Возврат;
КонецЕсли;

ФоновыеЗадания.Выполнить("...

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

  • Обновление данных ИБ при первом интерактивном запуске программы после обновления конфигурации;

  • Удаление объектов, помеченных на удаление;

  • Выгрузка данных информационной базы в файл для перехода в сервис;

  • Использования монопольного режима для снижения времени выполнения массовых операций по изменению данных;

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

На время выполнения этого фонового задания следует блокировать весь интерфейс приложения, открывая форму ожидания завершения операции в режиме РежимОткрытияОкна = БлокироватьВесьИнтерфейс. Блокировать интерфейс приложения требуется потому, что на время выполнения задания полноценная работа пользователя с приложением уже невозможна:

  • Если пользователь(*) попытается записать какой-либо объект, это приведет к ошибке (из-за установленного монопольного режима);
  • В ряде случаев могут запускаться фоновые задания в качестве реакции на действия пользователя случае (при поиске в динамическом списке, при вводе по строке, формировании отчетов и пр.), которые также завершатся с ошибкой. Кроме того, на самой форме ожидания длительной операции не следует размещать элементы управления, которые могут приводить к запуску таких фоновых заданий. Например: поля ввода, динамические списки и отчеты.

* Примечание: ошибки записи также возникают в тех случаях, когда объекты записываются программно, например, из обработчиков ожидания. В них также следует проверять монопольный режим согласно п.4.

См. также