Длительная операция во внешней обработке
Для выполнения длительных операций в версиях конфигурации на базе БСП 3.0/3.1 служит следующая функция в общем модуле ДлительныеОперации:
Функция ВыполнитьВФоне(Знач ИмяПроцедуры, Знач ПараметрыПроцедуры, Знач ПараметрыВыполнения) Экспорт
Описание этой функции в версии БСП 3.0 отличается от ее описания в версии БСП 3.1
Параметр ИмяПроцедуры – Это имя экспортной процедуры общего модуля, модуля менеджера объекта
или модуля обработки, которую необходимо выполнить в фоне., Например “МойОбщийМодуль.МояПроцедура”, “Отчеты.ЗагруженныеДанные.Сформировать”
или “Обработки.ЗагрузкаДанных.МодульОбъекта.Загрузить”.
Сложности возникают, когда обработка является внешне. В описании функции в версии БСП 3.0 написано так:
Запустить выполнение процедуры в фоновом задании, если это возможно.
При выполнении любого из следующих условий запуск выполняется не в фоне, а сразу в основном потоке:
- если вызов выполняется в файловой базе во внешнем соединении (в этом режиме фоновые задания не поддерживаются);
- если приложение запущено в режиме отладки (параметр /C РежимОтладки) – для упрощения отладки конфигурации;
- если в файловой ИБ имеются активные фоновые задания – для снижения времени ожидания пользователя;
- если выполняется процедура модуля внешней обработки или внешнего отчета.
- Не следует использовать эту функцию, если необходимо безусловно запускать фоновое задание.
- Может применяться совместно с функцией ДлительныеОперацииКлиент.ОжидатьЗавершение.
Согласно этому описанию, функция ВыполнитьВФоне в версии БСП 3.0 не выполняется в фоновом режиме если выполняется процедура модуля внешней обработки. Это не совсем так или я не совсем понял что, тут имеется ввиду. Тем не менее я решил показать простой пример выполнения длительной операции во внешней обработке для БСП 3.0/3.1.
Следует отметить, что в описании функции ВыполнитьВФоне в версии БСП 3.1 рекомендуется вместо этой функции использовать функции ВыполнитьФункцию и ВыполнитьПроцедуру.
Вызываемые функции могть быть с произвольным числом параметров, но не более 7. Значения передаваемых параметров функции, а также возвращаемое значение должны быть сериализуемыми.
Функция ВыполнитьФункцию(Знач ПараметрыВыполнения, ИмяФункции, Знач Параметр1 = Неопределено, Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено, Знач Параметр4 = Неопределено,Знач Параметр5 = Неопределено, Знач Параметр6 = Неопределено, Знач Параметр7 = Неопределено) Экспорт
ПараметрыВызова = СписокПараметров(Параметр1, Параметр2, Параметр3, Параметр4, Параметр5, Параметр6, Параметр7);
ПараметрыВыполнения = ПодготовитьПараметрыВыполнения(ПараметрыВыполнения, Истина);
Возврат ВыполнитьВФоне(ИмяФункции, ПараметрыВызова, ПараметрыВыполнения);
КонецФункции
Функция ВыполнитьПроцедуру(Знач ПараметрыВыполнения = Неопределено, ИмяПроцедуры, Знач Параметр1 = Неопределено,Знач Параметр2 = Неопределено, Знач Параметр3 = Неопределено, Знач Параметр4 = Неопределено,Знач Параметр5 = Неопределено, Знач Параметр6 = Неопределено, Знач Параметр7 = Неопределено) Экспорт
ПараметрыВызова = СписокПараметров(Параметр1, Параметр2, Параметр3, Параметр4,Параметр5,Параметр6, Параметр7);
ПараметрыВыполнения = ПодготовитьПараметрыВыполнения(ПараметрыВыполнения, Ложь);
Возврат ВыполнитьВФоне(ИмяПроцедуры, ПараметрыВызова, ПараметрыВыполнения);
КонецФункции
Особенность выполнения длительной операции во внешней обработке заключается в том, что она должна быть в списке справочника дополнительных внешних обработок. В общем виде процесс запуска и обработки результата длительной операции во внешней обработке выглядит следующим образом:
- Создать 2 реквизита в форме обработки как показано на рис. 1
2 При открытии обработки проверить открыто ли обработка из справочника внешних обработок и возможность запуска в фоне:
&НаСервере Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) ВнешняяОбработка = РеквизитФормыВЗначение("Объект"); // если обработка открыта из справочника проверим заполненность ссылки Параметры.Свойство("ДополнительнаяОбработкаСсылка", ДополнительнаяОбработкаСсылка); // если пустая значит открытие из вне, нужно поискать ее в справочнике Если ДополнительнаяОбработкаСсылка.Пустая() Тогда ДополнительнаяОбработкаСсылка = Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию(ВнешняяОбработка.Метаданные().Сионим); КонецЕсли; // если забыли добавить в справочник выполнить в фоне не получится : ДоступноВыполнениеВФоне = НЕ ДополнительнаяОбработкаСсылка.Пустая(); КонецПроцедуры
3) В модуле объекта внешней обработки я добавил процедуру расчета ВыполнитьРасчетВФоне , которая будет исполняться в фоне и функцию ВыполнитьРасчет. которая будет выполняться не фоне если не возможно выполнить расчет в фоне ( Следует отметить, что длительные процедуры должны располагаться только в менеджере объекта или в серверном общем модуле или в модуле внешней обработки):
Функция ВыполнитьРасчетНеВфоне(Параметры)Экспорт Параметр1 = Параметры.Параметр1; Параметр2 = Параметры.Параметр2; Результат = Параметр1+ Параметр2; Возврат Результат; КонецФункции Процедура ВыполнитьРасчетВФоне(Параметры, АдресРезультата) Экспорт Результат = ВыполнитьРасчетНеВфоне(Параметры); ПоместитьВоВременноеХранилище(Результат, АдресРезультата); КонецПроцедуры
3) Запуск операции на сервере и подключение обработчика ожидания если это возможно:
&НаКлиенте
Процедура ВыполнитьРасчет()
//создаем структуру параметров расчетов
ПараметрыРасчета = Новый Структура("Параметр1,Параметр2", 10, 20);
Если ДоступноВыполнениеВФоне Тогда
ДлительнаяОперация = НачатьВыполнениеВФонеНаСервере(ПараметрыРасчета);
ОповещениеОЗавершении = Новый ОписаниеОповещения("ОбработатьРезультат", ЭтотОбъект);
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, ОповещениеОЗавершении, ПараметрыОжидания);
Иначе
НачатьВыполнитьРасчетНеВФоне(ПараметрыРасчета ); //Не возможно
КонецЕсли;
КонецПроцедуры
4 )Начать расчет в фоне или не в фоне
//Это расчет в фоне &НаСервере Функция НачатьВыполнениеВФонеНаСервере(ПараметрыРасчета) //ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияФункции(УникальныйИдентификатор); // БСП 3.1 ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор); // БСП 3.0 ВыполняемыйМетод = "ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки"; ПараметрыЗадания = Новый Структура; ПараметрыЗадания.Вставить("ДополнительнаяОбработкаСсылка",ДополнительнаяОбработкаСсылка); ПараметрыЗадания.Вставить("ИмяМетода", "ВыполнитьРасчетВФоне"); ПараметрыЗадания.Вставить("ЭтоВнешняяОбработка", Истина); ПараметрыЗадания.Вставить("ПараметрыВыполнения",ПараметрыРасчета); РезультатВыполнения = ДлительныеОперации.ВыполнитьВФоне(ВыполняемыйМетод,ПараметрыЗадания, ПараметрыВыполнения); Возврат РезультатВыполнения; КонецФункции // Это результат расчета не в фоне &НаСервере Процедура НачатьВыполнитьРасчетНеВФоне(ПараметрыРасчета) ВнешняяОбработка = РеквизитФормыВЗначение("Объект"); Резултьат = ВнешняяОбработка.ВыполнитьРасчетНеВфоне(ПараметрыРасчета); КонецПроцедуры
Следует отметить, что функция ПараметрыВыполненияВФоне, которая возвращает структуру параметров выполнения отсутствует в БСП3.1.. Вместо этой функции используется ПараметрыВыполненияФункции и ПараметрыВыполненияПроцедуры
5) Обработка результата длительной операции:
&НаКлиенте
Процедура ОбработатьРезультат(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
Возврат;
КонецЕсли;
Если Результат.Статус = "Выполнено" Тогда
ТекстСообщения = ПолучитьИзВременногоХранилища(Результат.АдресРезультата);
ИначеЕсли Результат.Статус = "Ошибка" Тогда
ТекстСообщения = Результат.ПодробноеПредставлениеОшибки;
КонецЕсли;
Если Результат.Сообщения <> Неопределено Тогда
Для каждого СообщениеПользователю Из Результат.Сообщения Цикл
СообщениеПользователю.Сообщить();
КонецЦикла;
КонецЕсли;
ОбщегоНазначенияКлиент.СообщитьПользователю("Результат: "+ ТекстСообщения);
КонецПроцедуры
Следует отметить, что в качестве параметра нужно передать параметры, которые поддерживают серализацию, иначе длительная операция не выполняется и выдается сообщение -“Параметр фонового задания не поддерживает сериализацию” .
Например , если параметр ТаблицаДанных имеет тип ДанныеФормыЭлементКоллекции, то нужно преобразовать на тип ТаблицаЗначений с помощью метода выгрузить таким образом
Тз =ТаблицаДанных.Выгрузить();
ПараметрыВызова = Новый Структура(“Параметр1,Параметр2,Таблица”, 10, 20,Тз);
В описании механизма длительных операции написано, что все значения параметров фонового задания должны поддерживать сериализацию (речь идет о сериализации, а не о ХМL – сериализации). Сериализация — это преобразование объекта или дерева объектов в какой-либо формат с тем, чтобы потом эти объекты можно было восстановить из этого формата. А XML – сериализация – это процесс преобразования данных 1С:Предприятия 8 в последовательность данных формата XML и наоборот, прежде всего для обмена данными между различными информационными базами 1С:Предприятия.
Известно, сериализация данных применима для всех объектов 1С. Однако в документации по встроенному языку в описании объектов возможность сериализации указывается отметкой “Сериализуется“.
Например, в синтакс-помощнике объекта ТаблицаЗначений написано «Возможен обмен с сервером. Сериализуется. Данный объект может быть сериализован в/из XDTO. Тип XDTO, соответствующий данному объекту, определяется в пространстве имен {http://v8.1c.ru/8.1/data/core}. Имя типа XDTO: ValueTable»