UPDATE 20/09/19: добавлен вариант обработки с индикацией процента выполнения и статусом выполнения для БСП 3.0.
Не секрет, что после запуска "тяжелой" обработки хочется продолжать работать в программе, а также "видеть" время от времени сам процесс выполнения. Для простого пояснения, как это реализовано, и предназначена эта статья. Если ваша конфигурация не на БСП 2.3.2, можно сразу перейти, например, на эту статью //infostart.ru/public/157706/
Важно! Обработка должна использоваться только через штатный механизм БСП "Дополнительные отчеты и обработки".
Код модуля обработки
Примечание: обработку можно запустить как из формы (см. представление команды "Открыть форму и выполнить в фоне с индикацией") так и сразу на сервере (см представление команды "Выполняем на сервере"). Запуск непосредственно на сервере можно сделать по расписанию.
// Возвращает сведения о внешней обработке. Функция СведенияОВнешнейОбработке() Экспорт ПараметрыРегистрации = ДополнительныеОтчетыИОбработки.СведенияОВнешнейОбработке("2.2.2.1"); ПараметрыРегистрации.Вид = ДополнительныеОтчетыИОбработкиКлиентСервер.ВидОбработкиДополнительнаяОбработка(); ПараметрыРегистрации.Версия = "2.1"; ПараметрыРегистрации.БезопасныйРежим = Истина; НоваяКоманда = ПараметрыРегистрации.Команды.Добавить(); НоваяКоманда.Представление = НСтр("ru = 'Выполняем на сервере'"); НоваяКоманда.Идентификатор = "ВыполнениеНаСервереОбработку"; НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода(); НоваяКоманда.ПоказыватьОповещение = Истина; НоваяКоманда = ПараметрыРегистрации.Команды.Добавить(); НоваяКоманда.Представление = НСтр("ru = 'Открыть форму и выполнить в фоне с индикацией'"); НоваяКоманда.Идентификатор = "ОткрытьФормуОбработку"; НоваяКоманда.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы(); НоваяКоманда.ПоказыватьОповещение = Ложь; Возврат ПараметрыРегистрации; КонецФункции // Интерфейс для выполнения команд обработки. Процедура ВыполнитьКоманду(ИмяКоманды,ПараметрыВыполнения) Экспорт ДатаЗавершенияВМиллисекундах = ТекущаяУниверсальнаяДатаВМиллисекундах() + 1000*10; Попытка СтандартныеПодсистемыКлиентСервер.ВывестиОповещение( ПараметрыВыполнения.РезультатВыполнения, НСтр("ru = 'Выполнена длит. операция!'"),, БиблиотекаКартинок.Успешно32); Исключение СтандартныеПодсистемыКлиентСервер.ВывестиИнформациюОбОшибке( ПараметрыВыполнения.РезультатВыполнения, СтрШаблон(НСтр("ru = 'Ошибка выполнения команды ""%1""'"), ИмяКоманды), ИнформацияОбОшибке()); Возврат; КонецПопытки; //Имитация длительной операции - вместо этого вставте свой код который будет выполняться на сервере в фоне Пока ТекущаяУниверсальнаяДатаВМиллисекундах() < ДатаЗавершенияВМиллисекундах Цикл КонецЦикла; КонецПроцедуры
Код модуля формы обработки
Важно добавить в форму эти параметры:
- ДополнительнаяОбработкаСсылка (тип "СправочникСсылка.ДополнительныеОтчетыИОбработки").
- ИдентификаторКоманды (тип "Строка")
.. и эти реквизиты:
- ОбъектСсылка (тип "СправочникСсылка.ДополнительныеОтчетыИОбработки")
- ИдентификаторКоманды (тип "Строка")
&НаСервере Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка) ОбъектСсылка = Параметры.ДополнительнаяОбработкаСсылка; ИдентификаторКоманды = Параметры.ИдентификаторКоманды; КонецПроцедуры &НаКлиенте Процедура ОбработкаВыбора(ВыбранноеЗначение, ИсточникВыбора) Если ИсточникВыбора.ИмяФормы = ДополнительныеОтчетыИОбработкиКлиент.ИмяФормыДлительнойОперации() Тогда ЗагрузитьРезультат(ВыбранноеЗначение); КонецЕсли; КонецПроцедуры &НаКлиенте Процедура Фигачить(Команда) ПараметрыКоманды = Новый Структура("ДополнительнаяОбработкаСсылка, СопровождающийТекст"); ПараметрыКоманды.ДополнительнаяОбработкаСсылка = ОбъектСсылка; ПараметрыКоманды.СопровождающийТекст = НСтр("ru = 'Выполняем из формы в фоне...'"); Состояние(ПараметрыКоманды.СопровождающийТекст); ДополнительныеОтчетыИОбработкиКлиент.ВыполнитьКомандуВФоне(ИдентификаторКоманды, ПараметрыКоманды, ЭтаФорма); КонецПроцедуры &НаКлиенте Процедура ЗагрузитьРезультат(РезультатВыполнения) Если Открыта() Тогда Закрыть(); КонецЕсли; ДополнительныеОтчетыИОбработкиКлиент.ПоказатьРезультатВыполненияКоманды(ВладелецФормы, РезультатВыполнения); КонецПроцедуры &НаСервере Функция ВыполнитьКомандуНапрямую(ИдентификаторКоманды, ПараметрыКоманды) Возврат ДополнительныеОтчетыИОбработки.ВыполнитьКомандуИзФормыВнешнегоОбъекта(ИдентификаторКоманды, ПараметрыКоманды, ЭтаФорма); КонецФункции
Примечание: для формы нужно назначить обработчики событий для процедур "ПриСозданииНаСервере" и "ОбработкаВыбора".
Вот, собственно, и все…
З.Ы. Для тех, кому недостаточно "простого" описания и кто хочет подробно разобраться в предмете — см. описание с ИТС
UPDATE 20/09/19: добавил вариант обработки с индикацией процента выполнения и статусом выполнения для БСП 3.0.
Немного тут подсмотрел
Модуль обработки:
Процедура ВыполнитьКоманду(ИмяКоманды, ПараметрыВыполнения) Экспорт
Если ИмяКоманды = "ОткрытьФормуОбработку" Тогда
ВремяФиниша = ТекущаяДатаСеанса() + 100;
Пока ТекущаяДатаСеанса() < ВремяФиниша Цикл
Процент = 100 - (ВремяФиниша - ТекущаяДатаСеанса());
Если НЕ (Процент % 10) Тогда
ДлительныеОперации.СообщитьПрогресс(Процент, СтрШаблон("Выполнено %1 процентов: пример параметра команды = %2", Процент,ПараметрыВыполнения.СвойПараметр));
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецПроцедуры
Модуль формы:
&НаСервере
Функция ФигачитьВФоне(ВыполняемаяКоманда, УникальныйИдентификатор)
ПараметрыПроцедуры = Новый Структура("ДополнительнаяОбработкаСсылка, ИдентификаторКоманды, СвойПараметр");
ПараметрыПроцедуры.ДополнительнаяОбработкаСсылка = ВыполняемаяКоманда.Ссылка;
ПараметрыПроцедуры.ИдентификаторКоманды = ВыполняемаяКоманда.Идентификатор;
ПараметрыПроцедуры.СвойПараметр = ВыполняемаяКоманда.СвойПараметр;
ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
Возврат ДлительныеОперации.ВыполнитьВФоне("ДополнительныеОтчетыИОбработки.ВыполнитьКоманду", ПараметрыПроцедуры, ПараметрыВыполнения);
КонецФункции
&НаКлиенте
Процедура Фигачить(Команда)
СопровождающийТекст = НСтр("ru = 'Выполняется обработка данных'");
Обработчик = Новый ОписаниеОповещения("ПослеЗавершенияДлительнойОперации", ЭтотОбъект, СопровождающийТекст);
Если ЗначениеЗаполнено(Параметры.ДополнительнаяОбработкаСсылка) Тогда
НастройкиОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтаФорма);
НастройкиОжидания.ВыводитьПрогрессВыполнения = Истина;
НастройкиОжидания.ВыводитьСообщения = Истина;
НастройкиОжидания.ТекстСообщения = НСтр("ru = 'Выполняется обработка данных...'");
ВыполняемаяКоманда = Новый Структура("Ссылка, Идентификатор, СвойПараметр", Параметры.ДополнительнаяОбработкаСсылка, Параметры.ИдентификаторКоманды, "это мой параметр (фоновое)");
ОперацияВФоне = ФигачитьВФоне(ВыполняемаяКоманда, УникальныйИдентификатор);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ОперацияВФоне, Обработчик, НастройкиОжидания);
Иначе
Параметры.ИдентификаторКоманды = "ОткрытьФормуОбработку";
ПараметрыКоманды = ДополнительныеОтчетыИОбработкиКлиент.ПараметрыВыполненияКомандыВФоне(Параметры.ДополнительнаяОбработкаСсылка);
ПараметрыКоманды.СопровождающийТекст = СопровождающийТекст + "...";
ПараметрыКоманды.Вставить("СвойПараметр","это мой параметр");
Операция = ВыполнитьКомандуНапрямую(ПараметрыКоманды);
ВыполнитьОбработкуОповещения(Обработчик, Операция);
КонецЕсли;
КонецПроцедуры
#Область СлужебныеПроцедурыИФункции
&НаСервере
Функция ВыполнитьКомандуНапрямую(ПараметрыКоманды)
Операция = Новый Структура("Статус, КраткоеПредставлениеОшибки, ПодробноеПредставлениеОшибки");
Попытка
ДополнительныеОтчетыИОбработки.ВыполнитьКомандуИзФормыВнешнегоОбъекта(
Параметры.ИдентификаторКоманды,
ПараметрыКоманды,
ЭтотОбъект);
Операция.Статус = "Выполнено";
Исключение
Операция.КраткоеПредставлениеОшибки = КраткоеПредставлениеОшибки(ИнформацияОбОшибке());
Операция.ПодробноеПредставлениеОшибки = ПодробноеПредставлениеОшибки(ИнформацияОбОшибке());
КонецПопытки;
Возврат Операция;
КонецФункции
&НаКлиенте
Процедура ПослеЗавершенияДлительнойОперации(Операция, СопровождающийТекст) Экспорт
Если Операция.Статус = "Выполнено" Тогда
ПоказатьОповещениеПользователя(НСтр("ru = 'Успешное завершение'"), , СопровождающийТекст, БиблиотекаКартинок.Успешно32);
Иначе
ПоказатьПредупреждение(, Операция.КраткоеПредставлениеОшибки);
КонецЕсли;
КонецПроцедуры
#КонецОбласти
Добавьте в пример вывод прогресс-бара
(1) Fragster, можно конечно как тутhttp://infostart.ru/public/458778/ но пришлось бы снимать с поддержки для добавления своей общей формы. Другого способа более легкого не знаю )
(2) Зачем? есть же «ДлительныеОперации.СообщитьПрогресс» и «.ПрочитатьПрогресс», а отображать прогресс можно в своей форме с обработчиком ожидания? Или в данном случае это неприменимо?
(3) хм, посмотрю на досуге…
если запустить эту обработку в последней версии БП 3.0 то вместо «крутящегося колесика» — этот
веселый котэ )))
Настоящий подарок бухгалтерам )
(3) Fragster, у меня не получилось с индикатором в этом случае.
Дело в том что нет возможности получить «ИдентификаторЗадания» для использования
.
Вот если используется «ДлительныеОперации.ЗапуститьВыполнениеВФоне» тогда да это получиться:
Но это не для внешних обработок — остается только как вhttp://infostart.ru/public/159607/ самому запускать фоновое оповещать через «СообщениеПользователю» и «ловить» в форме в «обработчике ожидания».
А что за процедура Фигачить()? Она не используется по коду.
(7) это обработчик команды формы обработки
(5) И правда котэ в картинки «ДлительнаяОперация48» добавили 🙂
(5) бухгалтерия ЛИЧНО звонила и благодарила за «такого замечательного котика»
(8) есть опыт работы с длительными операциями для внешних отчетов? Делаем через набор данных «объект» и стандартная обработка в процедуре ПриКомпоновкеРезультата = ложь, поэтому стандартное скдшное фоновое задание не работает.
(11) aaudin90,
а зачем — отчет сервер смотрит ? ))
Отчет делается около 60 секунд, хотелось бы его каким то образом перевести в фон.
(13) aaudin90, примерно так: сделайте на сервере программный вывод из ПроцессорВыводаРезультатаКомпоновкиДанныхВТабличныйДокумент в табл документ, заполните в РезультатВыполнения табл.документ и на клиенте «ловите» этот РезультатВыполнения и демонстрируете его пользователю…
(14) спасибо за совет, но все таки отказались от идеи использования набора данных объект)
Здравствуйте! Что-то не могу допереть, как передать параметры в серверную экспортную процедуру ВыполнитьКоманду. Т.е., если длительная операция содержит выполнение запроса к базе, значения параметров вводятся через форму, как их подтянуть в процедуру? День протупил. 🙂 Буду очень признателен за помощь. Заранее спасибо.
(16) user595572_katigugu, поместить в «ПараметрыКоманды » в Фигачить()
например:
и получать в ВыполнитьКоманду(ИмяКоманды,ПараметрыВыполнения)
например:
(17) Спасибо большое.
На новом релизе бухгалтерии обработка перестала работать
(19) ну видимо БСП поменяли как обычно…
Вопрос: а как отлаживать фоновое? Отладчик не хочет заходить в созданный объект-обработку. Останавливается на Объект.Выполнить(ИмяКоманды,ПараметрыВыполнения)
Рассказываю рабочий способ: запускаем фоновое задание
И
Показать
Дальше для прогресс бара нам понадобится из запущенного сеанса выводить сообщения нужного нам формата, например «Прогресс=32». в основной обработке получаем эти сообщения и интерпретируем(парсим) через ПолучитьСообщенияПользователю() так:
И
Показать
На форме у меня Переменные ИдентификаторЗадания, Прогресс и Лог(многострочное текстовое поле для вывода прочих служебных сообщений).
(21)Отладку к сожалению можно делать только поставив галку на форме для отладки и по ней запускать процедуру непосредственно, не через фоновое задание. Если кто знает другой способ- мне и самому будет интересно узнать.
Отличная статья!
Показать
Этот код в версии БСП 2.3.5.65 не работает, просто его удалил!
И дописал свой код выполнения задания:
Передав в параметры выполнения список значения интеграция прошла на ура!
А в форме распараллеливание потоков написал:
Показать
Правда такой метод делает при не целом делении на 1 поток больше, но зато результат на лицо!
А есть идеи как передать ТЧ в фоновое задание?
Пробовал передать данные через ПоместитьВоВременноеХранилище. Но именно при фоновом запуске данные уже не получить.
PS: Пробовал использовать все три Варианта помещения данных, но ни один не заработал. Т.е на сервере ПолучитьИзВременногоХранилища всегда получается значение = неопределено.
(25) ну не знаю, может не серилизуемые данные и если не по идентификатору формы то один серв вызов живет ВХ. Попробуй параметр сеанса…
(26), точно не сериализуемые данные, пока выкрутился функцией ЗначениеВСтрокуВнутр и обратно, но данное решение мне не очень нравится.
А можешь поподробней про способ через параметр сеанса? типа помещать в какой-то из параметров данные и потом их оттуда забирать?
(27)да, верно
(22) это хорошо написали. Сейчас переписывал обработку, которая использует ключ ОткрытиеФормы, на ВызовСерверногоМетода.
И похоже чтобы регламентное задание разделило процедуру на куски нужна «Модуль.Процедура». Если нет модуля и процедуры, то ничего не выйдет я так понял!
(29) есть немного извращенный метод получать модули и процедуры из внешней обработки, но это надо передавать её целиком на сервер и сохранять там.
(30) а вот это уже интересно.
Речь идет именно о подключенной обработке?
Что за метод там используется, БСП?
(31) Да, БСП. ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки я тут описывал как делать:https://infostart.ru/public/842660/
(32) публикация не активна!
(33)теперь активна
А как вернуть значение из
или заполнить реквизит обработки/табличную часть?
Выполняю запрос, и через Сообщить() видно что запрос отрабатывает и идёт обход выборки, но заполнение не происходит
стр = тч.Добавить();
Сообщить(ВыборкаДетальныеЗаписи.Партнер);
ЗаполнитьЗначенияСвойств(Стр,ВыборкаДетальныеЗаписи);
КонецЦикла;
(35) тч — табчасть объекта ? да все должно ИМХО норм отрабатывать
ТЧ — таб часть объекта, командой «Открыть форму и выполнить в фоне с индикацией»
В фоне отрабатывает запрос, все партнеры через сообщить выводятся, но таб часть
на форме остается пустой
Показать
(37)
ах на форме )
ага это точно так форму тут обновлять намного сложнее чем использовать РеквизитФормыВЗначение() или ДанныеФормыВзначение()
Процедура ВыполнитьКомандуВФоне(Знач ИдентификаторКоманды, Знач ПараметрыКоманды, Знач Обработчик)
третий параметр это описание оповещения.
почему в него передается «ЭтаФорма» ?
(34) написал вам комментарий по статье, сыровата и тема не раскрыта, если сможете показать, что не так и дополнить статью, то будет отлично!
(40)ответил Вам там, метод рабочий и используется, думаю дополнить статью можно
(0) в своей логике не использовал передачу ТЗ с клиента в фоновое задание. Сейчас это понадобилось.
На форме есть данные формы коллекция. Через серверный вызов преобразовываю в ТЗ и помещаю во временное хранилище.
Как получить потом ТЗ в фоновом задании?
У меня не получилось! Передал адрес ТЗ на клиенте, а когда к нему обратилось фоновое задание, то там ничего не было.
Я так понимаю это особенность работы 1С. Был ли опыт такой работы?
(42)
Временное хранилище, сформированное в одном сеансе, недоступно из другого сеанса.
Фоновое задание — это и есть другой сеанс. А ТЗ осталась во ВХ клиентского сеанса.
Я сохранял данные во временном файле и передавал в фоновое путь к временному файлу на сервере.
(43) про это я написал. Решение вопроса, то есть?
(44) сохраняй в любом хранилище, не связанном с текущим сеансом. Например в хранилище внешней обработки (если это форма внешней обработки), в хранилище настроек конфигурации, в любом регистре сведений где есть ресурс с типом ХранилищеЗначения (например Версии объектов), сохраняй в файл в каталоге темп (если нужно передать файл)
(45) каким методом?
Я так понимаю этот метод только на сеанс.
(46) например
ХранилищеОбщихНастроек.Сохранить();
ХранилищеОбщихНастроек.Загрузить();
или
Новый хранилищеЗначения()
(47)
Отличный вариант! Как раз на клиенте вызываю серверную функцию, которая возвращает тип «ХранилищеЗначения», а далее передаю параметром в клиентский фоновый вызов!
Не забывайте в СведенияОВнешнейОбработке() указывать версию БСП.
Интересно какая минимальная версия для работы этого метода?
добавил вариант обработки с индикацией процента выполнения и статусом выполнения для БСП 3.0
))
(51) Да, помогла ваша публикация о чем я собственно и написал )
>>Немного тут подсмотрел
но в дополнение показал как доп. параметры передавать ну и использовал типовые приемы из внешней обработки «ЗаполнениеКонтрагентов» из БСП 3.0.3.