Добрый день, коллеги.
Основная идея обработки взята из публикации //infostart.ru/1c/articles/1112877/, т. е. чтобы запустить в фоновом задании процедуру модуля внешней обработки, надо создать копию этой обработки на сервере и уже запустить её методом "ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки" через функцию БСП ДлительныеОперации.ВыполнитьВФоне. Впрочем БСП делает практически тоже самое для обработок подключенных к подсистеме "ДополнительныеОтчетыИОбработки".
Обработка писалась для себя как шаблон, что бы не вспоминать что и где надо исправить, ну и те примеры, которые уже есть на эту тему не очень удовлетворяли меня.
Собственно код:
Модуль обработки
#Область ПрограммныйИнтерфейс
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке(СтандартныеПодсистемыСервер.ВерсияБиблиотеки());
ПараметрыРегистрации.Наименование = НСтр("ru = 'ШаблонОбработкиДлительнойОперацииСПрогрессом'");
ПараметрыРегистрации.Информация = НСтр("ru = 'Шаблон обработки с длительной операцией и выводом прогресса '");
ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка();
ПараметрыРегистрации.Версия = "1.1.1";
ПараметрыРегистрации.БезопасныйРежим = Ложь;
Команда = ПараметрыРегистрации.Команды.Добавить();
Команда.Представление = НСтр("ru = 'Открытие формы обработки...'");
//Для совместимости Идентификатор называем также как и процедуру модуля
Команда.Идентификатор = "ВыполнитьДлительнуюОперацию";
Команда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();
Команда.ПоказыватьОповещение = Ложь;
Возврат ПараметрыРегистрации;
КонецФункции
//Имитация длительной операции
Процедура ВыполнитьДлительнуюОперацию(ПараметрыОбработки, АдресРезультата) Экспорт
СчетчикШага = 0;
Шаг = ПараметрыОбработки.КоличествоИтераций / 100;
Для Счетчик = 1 По ПараметрыОбработки.КоличествоИтераций Цикл
ДатаЗавершенияВМиллисекундах = ТекущаяУниверсальнаяДатаВМиллисекундах() + 1000;
Пока ТекущаяУниверсальнаяДатаВМиллисекундах() < ДатаЗавершенияВМиллисекундах Цикл
КонецЦикла;
//БСП рекомендует вызывать ДлительныеОперации.СообщитьПрогресс не более 100 раз
Если (Счетчик - СчетчикШага) >= Шаг Тогда
СчетчикШага = Счетчик;
ПроцентВыполнения = Цел(Счетчик * 100 / ПараметрыОбработки.КоличествоИтераций);
ТестСообщения = СтрШаблон("Выполнено %1 из %2", Счетчик, ПараметрыОбработки.КоличествоИтераций);
ДлительныеОперации.СообщитьПрогресс(ПроцентВыполнения, ТестСообщения);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
#КонецОбласти
В форме созданы следующие реквизиты:
- ИдентификаторДлительнойОперации - ТИП "УникальныйИдентификатор" используется для поиска и управления фоновым заданием
- ИдентификаторКомандыОбработки - ТИП "Строка"
- ИмяФайлаОбработки - ТИП "Строка" эти два реквизита для универсальности использования обработки как с подключением к БСП "ДополнительныеОтчетыИОбработки" и так и без нее
- ДлительнаяОперацияПроцент - Тип "Число" для вывода прогресса выполнения
- ДлительнаяОперацияТекст - Тип "Строка" для вывода текста прогресса выполнения, если использовать стандартный вывод БСП, то эти реквизиты не нужны.
Код модуля формы
#Область СобытияФормы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если ЗначениеЗаполнено(Параметры.ДополнительнаяОбработкаСсылка) Тогда
ИмяФайлаОбработки = ОбщегоНазначения.ЗначениеРеквизитаОбъекта(Параметры.ДополнительнаяОбработкаСсылка, "ИмяФайла");
ИдентификаторКомандыОбработки = Параметры.ИдентификаторКоманды;
Иначе
ИмяФайлаОбработки = "";
ИдентификаторКомандыОбработки = "ВыполнитьДлительнуюОперацию";
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
Если ЗначениеЗаполнено(ИдентификаторДлительнойОперации) Тогда
ПроверитьИОтменитьЕслиВыполняется(ИдентификаторДлительнойОперации);
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиКомандФормы
&НаКлиенте
Процедура ВыполнитьОбработку(Команда)
Если НЕ ЗначениеЗаполнено(ИмяФайлаОбработки) И Не СоздатьКопиюНаСервере() Тогда
ПоказатьПредупреждение(,"Не удалось создать временный файл на сервере",, "Ошибка!!!");
Возврат;
КонецЕсли;
ПараметрыОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
//Если требуется стандарный вывод БСП тогда снять комментарий у следующих 2 строк
//ПараметрыОжидания.ВыводитьОкноОжидания = ИСТИНА
//ПараметрыОжидания.ВыводитьПрогрессВыполнения = Истина;
//и закомментировать следующие 2 строки
ПараметрыОжидания.ВыводитьОкноОжидания = Ложь;
ПараметрыОжидания.ОповещениеОПрогрессеВыполнения = Новый ОписаниеОповещения("ПрогрессВыполнения", ЭтотОбъект);
ПараметрыОжидания.ОповещениеПользователя.Показать = Истина;
ПараметрыОжидания.ОповещениеПользователя.Текст = НСтр("ru = 'Успешное завершение'");
ПараметрыОжидания.Интервал = 1;
ОповещениеПослеВыполнения = Новый ОписаниеОповещения("ПослеЗавершенияДлительнойОперации", ЭтотОбъект);
СтруктураДлительнойОперации = НачатьВыполнениеДлительнойОперации();
ДлительныеОперацииКлиент.ОжидатьЗавершение(СтруктураДлительнойОперации, ОповещениеПослеВыполнения, ПараметрыОжидания);
Если СтруктураДлительнойОперации.Статус = "Выполняется" Тогда
ИдентификаторДлительнойОперации = СтруктураДлительнойОперации.ИдентификаторЗадания;
//Если требуется стандарный вывод БСП тогда закомментировать следующие 4 строки
Элементы.Страницы.ТекущаяСтраница = Элементы.ДлительныеОперации;
Элементы.ГруппаКнопки.Видимость = Ложь;
ДлительнаяОперацияПроцент = 0;
ДлительнаяОперацияТекст = НСтр("ru = 'Пожалуйста подождите...'");
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
&НаСервере
Функция СоздатьКопиюНаСервере()
Попытка
ИмяФайлаОбработки = ПолучитьИмяВременногоФайла("epf");
//Если у пользователя ИБ установлен режим "Защита от опасных действий"
//следующие 2 строчки вызывют ошибку поскольку в этом режиме они блокируются
//Решение: подключать обработку к подсистеме "ДополнительныеОтчетыИОбрабоки"
ДвоичныеДанные = Новый ДвоичныеДанные(РеквизитФормыВЗначение("Объект").ИспользуемоеИмяФайла);
ДвоичныеДанные.Записать(ИмяФайлаОбработки);
Результат = Истина;
Исключение
ИмяФайлаОбработки = "";
Результат = Ложь;
КонецПопытки;
Возврат Результат;
КонецФункции
&НаСервере
Функция НачатьВыполнениеДлительнойОперации()
//Собственные параметры задания
ПараметрыВыполненияОбработки = Новый Структура;
ПараметрыВыполненияОбработки.Вставить("КоличествоИтераций", КоличествоИтераций);
//Стандартные параметры задания
ПараметрыЗадания = Новый Структура;
ПараметрыЗадания.Вставить("ИмяОбработки", ИмяФайлаОбработки);
ПараметрыЗадания.Вставить("ИмяМетода", ИдентификаторКомандыОбработки);
ПараметрыЗадания.Вставить("ПараметрыВыполнения", ПараметрыВыполненияОбработки);
ПараметрыЗадания.Вставить("ДополнительнаяОбработкаСсылка", Параметры.ДополнительнаяОбработкаСсылка);
ПараметрыЗадания.Вставить("ЭтоВнешняяОбработка", Истина);
ВыполняемыйМетод = "ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки";
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
ПараметрыВыполнения.НаименованиеФоновогоЗадания = СтрШаблон("Фоновое выполнение обработки %1", ПараметрыЗадания.ИмяОбработки);
Результат = ДлительныеОперации.ВыполнитьВФоне(ВыполняемыйМетод, ПараметрыЗадания, ПараметрыВыполнения);
Возврат Результат;
КонецФункции
&НаКлиенте
// Если используется стандартный вывод БСП в процедуре нет необходимости
Процедура ПрогрессВыполнения(Результат, ДополнительныеПараметры) Экспорт
Если Результат.Статус = "Выполняется" Тогда
Прогресс = ПрочитатьПрогресс(Результат.ИдентификаторЗадания);
Если Прогресс <> Неопределено Тогда
ДлительнаяОперацияПроцент = Прогресс.Процент;
ДлительнаяОперацияТекст = Прогресс.Текст;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ПрочитатьПрогресс(ИдентификаторЗадания)
Возврат ДлительныеОперации.ПрочитатьПрогресс(ИдентификаторЗадания);
КонецФункции
&НаКлиенте
Процедура ПослеЗавершенияДлительнойОперации(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
Возврат;
КонецЕсли;
Если Результат.Статус = "Выполнено" Тогда
// Если используется стандартный вывод БСП закомментировать следующие 3 строчки
ДлительнаяОперацияПроцент = 100;
Элементы.Страницы.ТекущаяСтраница = Элементы.НастройкиОбработки;
Элементы.ГруппаКнопки.Видимость = Истина;
Иначе
ПоказатьПредупреждение(, Результат.КраткоеПредставлениеОшибки);
КонецЕсли;
КонецПроцедуры
&НаСервереБезКонтекста
Процедура ПроверитьИОтменитьЕслиВыполняется(ИдентификаторЗадания)
ДлительнаяОперация = ДлительныеОперации.ОперацияВыполнена(ИдентификаторЗадания);
Если ДлительнаяОперация.Статус = "Выполняется" Тогда
ДлительныеОперации.ОтменитьВыполнениеЗадания(ИдентификаторЗадания);
КонецЕсли;
КонецПроцедуры
#КонецОбласти
Обработка тестировалась на версиях БСП 3.1.5.385 и 3.1.7.37 платформа 1с версии 8.3.20.1710