Произвольный код в фоновом режиме

03.09.18

Разработка - Механизмы платформы 1С

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

Механизм фоновых заданий все чаще используется для распаралеливания задач. Подвисающее на несколько минут окно - уже не комильфо, а для каждой длительной операции пользователь хочет видеть прогресс бар. И все бы ничего пока код пишет программист, вставляет в конфигурацию и потом запускает, но как быть если код пишется в процессе и заранее не известен? Менеджер фоновых заданий для процедуры "Запустить" требует имя процедуры, код есть только в виде строки. Ограничения платформы? Не в этот раз!

Итак, прежде чем прикручивать педали, посмотрим что уже есть в БСП: ВыполнитьПроцедуруМодуляОбъектаОбработки(Параметры, АдресХранилища). Заполняем параметры:

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

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

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


&НаСервере
Функция АдресФайлаОбработки()
	Возврат РеквизитФормыВЗначение("Объект").ИспользуемоеИмяФайла;
КонецФункции

Итак, файл записали на сервере, запускаем фоновое задание, которому говорим запустить функцию из БСП, которая запустит наш метод из этого файла внешней обработки:

ДвоичныеДанныеНаСервере = ПолучитьИзВременногоХранилища(ФайлОбработкиВоВременномХранилище);
            АдресФайлаНаСервере = КаталогВременныхФайлов()+ИмяФайла;
            ДвоичныеДанныеНаСервере.Записать(АдресФайлаНаСервере);
            
            СтруктураПараметров = Новый Структура("РезультатЗапроса,Код,Параметры",Результат[Результат.ВГраница()],Код,ПараметрыЗапроса);    

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

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

ПодключитьОбработчикОжидания("ПроверкаФоновогоЗадания",1,Ложь);

&НаКлиенте
Процедура ПроверкаФоновогоЗадания()
	
	Результат=ПроверкаФоновогоЗаданияНаСервере();
	Если Результат = Неопределено Тогда
		УбитьПроцесс(Неопределено);
	Иначе
		Если НЕ Результат.Состояние = "Задание выполняется" Тогда
			УбитьПроцесс(Неопределено);
		КонецЕсли;
	КонецЕсли;
	//Состояние("Выполняется алгоритм...",ПрогрессОбработки);
КонецПроцедуры

Функция ПроверкаФоновогоЗаданияНаСервере()
	Результат = Новый Структура("Прогресс,Состояние");
		
	Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
	ЗаполнитьЗначенияСвойств(Результат,Задание);
	Результат.Состояние= СТрока(Результат.Состояние);
	Если Задание = Неопределено Тогда
		Возврат Неопределено;
	Иначе
		
		Сообщения=Задание.ПолучитьСообщенияПользователю(Ложь);
		Для Каждого Сообщение ИЗ Сообщения Цикл
			Если Лев(Сообщение.Текст,1) <> "{" Тогда
				Сообщить(Сообщение.Текст);
			КонецЕсли;
		КонецЦикла;
		Прогресс = ДлительныеОперации.ПрочитатьПрогресс(ИдентификаторЗадания);
		Если Прогресс <> Неопределено Тогда
			ПрогрессОбработки = Прогресс.Процент;//?(Прогресс.Процент<>0,Прогресс.Процент,ПрогрессОбработки);
		КонецЕсли;
		Результат.Вставить("Прогресс",Прогресс);
	КонецЕсли;

	Возврат Результат;
КонецФункции

&НаКлиенте
Процедура УбитьПроцесс(Команда)
	
	УбитьПроцессНаСервере();
	ОтключитьОбработчикОжидания("ПроверкаФоновогоЗадания");
	Сообщить(""+ТекущаяДата()+" задание выполнено");
	
КонецПроцедуры

&НаСервере
Процедура УбитьПроцессНаСервере()
	Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
	Задание.Отменить();
	Элементы.ГруппаФоновоеЗадание.Видимость=Ложь;
КонецПроцедуры

Стоит обратить внимание что в процедуре, исполняемой во внешней обработке можно выводить сообщения, но для вывода прогресса стоит использовать ДлительныеОперации.СообщитьПрогресс(Прогресс). В проверке задания на клиенте можно использовать метод Состояние("Выполняется алгоритм...",ПрогрессОбработки); где прогресс обработки - наше полученное из фонового задания значение прогресса. в этом случае в нижнем правом углу появится окно с процентами, которое будет видно даже если переключиться на другую вкладку, но лично мне это эстетически не нравится, и я рекомендую создать полосу с процентами на форме и менять значение там.

Все описанные методы постоянно используются мной при создании обработок и периодически дорабатываются. Будут предложения как улучшить - пишите в комментариях, если сам допилю - обновлю статью. Всем Удачи!

См. также

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

23.06.2024    7457    bayselonarrend    20    

154

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

Пример использования «Сервисов интеграции» без подключения к Шине и без обменов.

13.03.2024    5946    dsdred    16    

80

Механизмы платформы 1С Программист Стажер Платформа 1С v8.3 Бесплатно (free)

Все мы используем массивы в своем коде. Это один из первых объектов, который дают ученикам при прохождении обучения программированию. Но умеем ли мы ими пользоваться? В этой статье я хочу показать все методы массива, а также некоторые фишки в работе с массивами.

24.01.2024    17673    YA_418728146    26    

71

Перенос данных 1C Механизмы платформы 1С Системный администратор Программист Стажер Платформа 1С v8.3 Бесплатно (free)

Вы все еще регистрируете изменения только на Планах обмена и Регистрах сведений?

11.12.2023    11225    dsdred    44    

130

Механизмы платформы 1С Программист Бесплатно (free)

Язык программирования 1С содержит много нюансов и особенностей, которые могут приводить к неожиданным для разработчика результатам. Сталкиваясь с ними, программист начинает лучше понимать логику платформы, а значит, быстрее выявлять ошибки и видеть потенциальные узкие места своего кода там, где позже можно было бы ещё долго медитировать с отладчиком в поисках источника проблемы. Мы рассмотрим разные примеры поведения кода 1С. Разберём результаты выполнения и ответим на вопросы «Почему?», «Как же так?» и «Зачем нам это знать?». 

06.10.2023    23763    SeiOkami    48    

135

Механизмы платформы 1С Системный администратор Платформа 1С v8.3 Бесплатно (free)

Начиная с версии платформы 8.3.22 1С снимает стандартные блокировки БД на уровне страниц. Делаем рабочий скрипт, как раньше.

14.09.2023    18833    human_new    27    

80

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

При работе с интеграциями рано или поздно придется столкнуться с получением JSON файлов. И, конечно же, жизнь заставит проверять файлы перед тем, как записывать данные в БД.

28.08.2023    14734    YA_418728146    7    

166
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. Infactum 318 03.09.18 17:26 Сейчас в теме
Чем типовые механизмы БСП не угодили? Там еще и контроль доступа для фонового задания задействовать можно будет.
DrAku1a; kiruha; +2 Ответить
2. zarankony 311 03.09.18 22:36 Сейчас в теме
(1) читал я про эти методы, к сожалению нет идентификатора задания, а хотелось бы получать прогресс и выводить сообщения из фонового задания. а то от обычного кружка или котика радости мало))
BigB; DrAku1a; Vlad33k; +3 Ответить
3. RocKeR_13 1366 04.09.18 15:37 Сейчас в теме
4. zarankony 311 04.09.18 16:31 Сейчас в теме
(3) о да, она даже у меня в закладках есть) там есть привязка к "ИмяМодуля.ИмяЭкспортнойПроцедуры", ещё и замена общей формы, а задача - реализовать без изменения конфигурации.
5. Malfarion 261 04.09.18 18:52 Сейчас в теме
(4) Привет, не пробовал такой хак пройдет аудит на Fresh ? С учетом того что обработка во внешних, из файла понятно что не возьмет.
6. zarankony 311 04.09.18 21:46 Сейчас в теме
(5) Нет, не пробовал, попробуй - нам расскажешь.
7. Malfarion 261 05.09.18 01:05 Сейчас в теме
19. vadim1011985 101 03.11.18 01:04 Сейчас в теме
(2) Вот сегодня реализовал подобную хотелку
&НаКлиенте
//Процедура запускает загрузку и анализ файлов выгрузки 
// 
Процедура ЗагрузитьИЗаписать(Команда)
	
	Состояние("Начало загрузки",1,"Начало загрузки данных");
		
	ПараметрыКоманды = 
  ДополнительныеОтчетыИОбработкиКлиент.ПараметрыВыполненияКомандыВФоне(Параметры.ДополнительнаяОбработкаСсылка);
	
	ПараметрыКоманды.СопровождающийТекст = НСтр("ru = 'Подождите идет загрузка данных'");
	
	ПараметрыКоманды.ФормаВладелец = ЭтаФорма;
	
	ПараметрыКоманды.Вставить("Каталог", Объект.Каталог);
	//ПараметрыКоманды.Вставить("Объект",Объект);
	ПараметрыКоманды.Вставить("ТипЗагрузкиДокументов",Объект.ТипЗагрузкиДокументов);
	ПараметрыКоманды.Вставить("НачПериода",Объект.НачПериода);
	ПараметрыКоманды.вставить("КонПериода",Объект.КонПериода);
	
	Обработчик = Новый ОписаниеОповещения("ПослеЗавершенияДлительнойОперации", ЭтотОбъект, ПараметрыКоманды.СопровождающийТекст); 
	
	ОбработчикПрогресса =  Новый ОписаниеОповещения("ПрогрессВыполнения", ЭтотОбъект);
				
	ВыполнитьКомандуВФоне(Параметры.ИдентификаторКоманды, ПараметрыКоманды, Обработчик,ОбработчикПрогресса);

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

/// Процедура повторяет код общего модуля ДлительныеОперации.ВыпонитьвФоне . добавлен параметр оповещение о прогрессе выполнения. плюс изменены параметры структуры настройки ожидания

&НаКлиенте
Процедура ВыполнитьКомандуВФоне(Знач ИдентификаторКоманды, Знач ПараметрыКоманды, Знач Обработчик, Знач ОповещениеОПрогрессеВыполнения ) Экспорт
	
	ИмяПроцедуры = "ДополнительныеОтчетыИОбработкиКлиент.ВыполнитьКомандуВФоне";
	ОбщегоНазначенияКлиентСервер.ПроверитьПараметр(
		ИмяПроцедуры,
		"ИдентификаторКоманды",
		ИдентификаторКоманды,
		Тип("Строка"));
	ОбщегоНазначенияКлиентСервер.ПроверитьПараметр(
		ИмяПроцедуры,
		"ПараметрыКоманды",
		ПараметрыКоманды,
		Тип("Структура"));
	ОбщегоНазначенияКлиентСервер.ПроверитьПараметр(
		ИмяПроцедуры,
		"ПараметрыКоманды.ДополнительнаяОбработкаСсылка",
		ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыКоманды, "ДополнительнаяОбработкаСсылка"),
		Тип("СправочникСсылка.ДополнительныеОтчетыИОбработки"));
	ОбщегоНазначенияКлиентСервер.ПроверитьПараметр(
		ИмяПроцедуры,
		"Обработчик",
		Обработчик,
		Новый ОписаниеТипов("ОписаниеОповещения, УправляемаяФорма"));
	
	ПараметрыКоманды.Вставить("ИдентификаторКоманды", ИдентификаторКоманды);
	ПолучатьРезультат = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыКоманды, "ПолучатьРезультат", Ложь);
	
	Форма = Неопределено;
	Если ПараметрыКоманды.Свойство("ФормаВладелец", Форма) Тогда
		ПараметрыКоманды.ФормаВладелец = Неопределено;
	КонецЕсли;
	Если ТипЗнч(Обработчик) = Тип("ОписаниеОповещения") Тогда
		ОбщегоНазначенияКлиентСервер.ПроверитьПараметр(ИмяПроцедуры, "Обработчик.Модуль",
			Обработчик.Модуль,
			Тип("УправляемаяФорма"));
		Форма = ?(Форма <> Неопределено, Форма, Обработчик.Модуль);
	Иначе
		Форма = Обработчик;
		Обработчик = Неопределено;
		ПолучатьРезультат = Истина; // для обратной совместимости
	КонецЕсли;
	
	Задание = ДополнительныеОтчетыИОбработкиВызовСервера.ЗапуститьДлительнуюОперацию(Форма.УникальныйИдентификатор, ПараметрыКоманды);
	
	СопровождающийТекст = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыКоманды, "СопровождающийТекст", "");
	Заголовок = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыКоманды, "Заголовок");
	Если ЗначениеЗаполнено(Заголовок) Тогда
		СопровождающийТекст = СокрЛП(Заголовок + Символы.ПС + СопровождающийТекст);
	КонецЕсли;
	Если Не ЗначениеЗаполнено(СопровождающийТекст) Тогда
		СопровождающийТекст = НСтр("ru = 'Команда выполняется.'");
	КонецЕсли;
	
	//ОповещениеОПрогрессеВыполнения = Новый ОписаниеОповещения("ПрогрессВыполнения", ЭтотОбъект);
	
	НастройкиОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтаФорма);
	НастройкиОжидания.ТекстСообщения       = СопровождающийТекст;
	НастройкиОжидания.ВыводитьОкноОжидания = Ложь; // Ставим ложь что бы убрать котика 
	НастройкиОжидания.ВыводитьПрогрессВыполнения = Истина;
	НастройкиОжидания.ПолучатьРезультат    = ПолучатьРезультат; // для обратной совместимости
	НастройкиОжидания.ВыводитьСообщения    = Истина;
	НастройкиОжидания.ОповещениеОПрогрессеВыполнения = ОповещениеОПрогрессеВыполнения;  // задаем наше оповещение о прогрессе выполнения  
	
	
	ДлительныеОперацииКлиент.ОжидатьЗавершение(Задание, Обработчик, НастройкиОжидания);
	
КонецПроцедуры


&НаКлиенте
Процедура ПрогрессВыполнения(Результат, ДополнительныеПараметры) Экспорт

		
	Если Результат.Статус = "Выполняется" Тогда
		Прогресс = Результат.Прогресс;
		Если Прогресс <> Неопределено Тогда
			
			Состояние (Прогресс.Текст, Прогресс.Процент,,);	
	     КонецЕсли;
	
	КонецЕсли;

КонецПроцедуры
Показать


Ну и соотвественно для сообщения прогресса использую ДлительныеОперации.СообщитьПроцесс
31. km_if 21.08.19 21:18 Сейчас в теме
(19) На БСП 3 также пытался сделать, не передаются некоторые параметры, пишет "Параметры не могут быть сериализованы".
Строки и числа передаются в ПараметрыКоманды, а что посложнее можно запихать в эти параметры, но выскакивает ошибка.
Кроме того, без БСП процедуры и функции в модуле объекта видят реквизиты объекта, а если запускать через длительную операцию, то ничего не видят - все значения пустые.
Непонятно как этим пользоватся, как сложные типы данных передавать для выполнения в длительную операцию на БСП 3?
8. asved.ru 36 05.09.18 09:25 Сейчас в теме
Необходимо понимать, что объект внешней обработки, вызов метода которого выполняется в фоне - не тот же самый объект, форма которого открыта на клиенте.
9. zarankony 311 05.09.18 12:01 Сейчас в теме
(8) Да, контекст в этом случае конечно отвалится. Я вообще вызываю процедуру из модуля объекта этой внешней обработки и туда передаю все что нужно. Рабочий пример если интересно здесь - https://infostart.ru/public/585055/ это по сути мой рабочий инструмент.
10. paybaseme 14 04.10.18 09:53 Сейчас в теме
Спасибо! Утащил к себе.
11. Xershi 1555 07.10.18 15:08 Сейчас в теме
Разрозненные куски кода, почти не понятно что и откуда.
Я так понимаю тут речь идет о том как внешнюю не подключенную обработку, запущенную через файл выполнить в фоне.
В целом получилось.
Добавил на форму реквизит "ПрогрессОбработки", число. После того как убрал комент в
Состояние("Выполняется алгоритм...",ПрогрессОбработки);

Также добавил на форму реквизит "ИдентификаторЗадания", УникальныйИдентификатор.
Как сделать прогресс бар без состояния не понятно.
Если база файловая и запущена через конфигуратор в отладке, фоновое задание не стартует, но это уже вопрос к БСП.
Если подключить обработку во внешние вываливается ошибка при сохранении, я так понимаю для подключения не задумывалось.

Сделал вот такую команду:
&НаСервере
Процедура Команда1НаСервере(ФайлОбработкиВоВременномХранилище)
	
	ИмяФайла = "Загрузка курсов валют НБРБ 2.0.epf";
	
	ДвоичныеДанныеНаСервере = ПолучитьИзВременногоХранилища(ФайлОбработкиВоВременномХранилище);
	АдресФайлаНаСервере = КаталогВременныхФайлов() + ИмяФайла;
	ДвоичныеДанныеНаСервере.Записать(АдресФайлаНаСервере);
	
	//СтруктураПараметров = Новый Структура("РезультатЗапроса,Код,Параметры", Результат[Результат.ВГраница()],Код,ПараметрыЗапроса);    
	
	ОбъектВЗначении = РеквизитФормыВЗначение("Объект");
	ТекущийСписокВалют = ОбъектВЗначении.СписокВалют.Выгрузить();
	
	СтруктураПараметров = Новый Структура();
	СтруктураПараметров.Вставить("ДополнительнаяОбработкаСсылка",	Объект.ОбъектСсылка);
	//ПараметрыКоманды.Вставить("АдресРезультата",				ПоместитьВоВременноеХранилище(Неопределено, Новый УникальныйИдентификатор()));
	СтруктураПараметров.Вставить("СопровождающийТекст",				НСтр("ru = 'Выполняется загрузка курсов валют...'"));
	//СтруктураПараметров.Вставить("СписокВалют",						ПолучитьАдресТаблицыВалют());
	СтруктураПараметров.Вставить("СписокВалют",						ТекущийСписокВалют);
	СтруктураПараметров.Вставить("НачалоПериода",					Объект.НачалоПериода);
	СтруктураПараметров.Вставить("ОкончаниеПериода",				Объект.ОкончаниеПериода);
	
	
	НаименованиеЗадания = НСтр("ru = 'Длительная операция внешней обработки'");
	
	ВыполняемыйМетод = "ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки";
	
	ПараметрыЗадания = Новый Структура;
	ПараметрыЗадания.Вставить("ИмяОбработки", АдресФайлаНаСервере);
	ПараметрыЗадания.Вставить("ИмяМетода", "ВыполнитьКоманду");
	ПараметрыЗадания.Вставить("ПараметрыВыполнения", СтруктураПараметров);
	ПараметрыЗадания.Вставить("ЭтоВнешняяОбработка", Истина);
	ПараметрыЗадания.Вставить("ДополнительнаяОбработкаСсылка",Неопределено);
	//ПараметрыЗадания.Вставить("ДополнительнаяОбработкаСсылка", Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию("Длительная операция"));
	
	ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
	ПараметрыВыполнения.НаименованиеФоновогоЗадания = НаименованиеЗадания;
	
	РезультатФоновогоЗадания = ДлительныеОперации.ЗапуститьВыполнениеВФоне(УникальныйИдентификатор, ВыполняемыйМетод, ПараметрыЗадания, ПараметрыВыполнения);
	
	ИдентификаторЗадания = РезультатФоновогоЗадания.ИдентификаторЗадания;
	
КонецПроцедуры

&НаКлиенте
Процедура Команда1(Команда)
	
	ДвоичныеДанные = Новый ДвоичныеДанные(АдресФайлаОбработки());
	ФайлОбработкиВоВременномХранилище = ПоместитьВоВременноеХранилище(ДвоичныеДанные);
	
	Команда1НаСервере(ФайлОбработкиВоВременномХранилище);
	
	ПодключитьОбработчикОжидания("ПроверкаФоновогоЗадания", 1, Ложь);

КонецПроцедуры
Показать

Нужно еще назначить "имя файла" или на форме указывать, решил просто переменной записать.
ПараметрыЗадания.Вставить("ИмяМетода", 

Тут я так понял автор не сделал ремарку и не уточнил что это ваша процедура которая будет длительно выполняться. У меня в модуле обработки экспортная процедура в стиле БСП "ВыполнитьКоманду".
Также в "СтруктураПараметров" нужно указать ваши параметры, а не то что у автора. И вам нужно будет полностью под себя это сделать.
Плюс переписал
&НаСервере
Функция ПроверкаФоновогоЗаданияНаСервере()
	
	Результат = Новый Структура("Прогресс, Состояние");
		
	Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
	Если Задание = Неопределено Тогда
		Возврат Неопределено;
	Иначе
		
		ЗаполнитьЗначенияСвойств(Результат, Задание);
		Результат.Состояние = Строка(Результат.Состояние);
		Сообщения=Задание.ПолучитьСообщенияПользователю(Ложь);
		Для Каждого Сообщение ИЗ Сообщения Цикл
			Если Лев(Сообщение.Текст,1) <> "{" Тогда
				Сообщить(Сообщение.Текст);
			КонецЕсли;
		КонецЦикла;
		Прогресс = ДлительныеОперации.ПрочитатьПрогресс(ИдентификаторЗадания);
		Если Прогресс <> Неопределено Тогда
			ПрогрессОбработки = Прогресс.Процент;//?(Прогресс.Процент<>0,Прогресс.Процент,ПрогрессОбработки);
		КонецЕсли;
		Результат.Вставить("Прогресс",Прогресс);
	КонецЕсли;

	Возврат Результат;
КонецФункции
Показать


В итоге что-то и вышло, но толку ноль.
По https://infostart.ru/public/525648/ уже писал обработку. Результат есть, но прогресса нет.
compaud; Franchiser; +2 Ответить
12. zarankony 311 08.10.18 09:35 Сейчас в теме
(11)Да, ПрогрессОбработки и ИдентификаторЗадания надо добавлять на форму, это стоило указать хотя мне и казалось чем-то само собой разумеющимся. Имя файла проще всего получить через функцию
РеквизитФормыВЗначение("Объект").ИспользуемоеИмяФайла;

Ошибка при сохранении связана с безопасным режимом, если у Вас полные права, то такой проблемы не возникает.
Чтобы не выводить прогресс через состояние для ПрогрессОбработки сделайте Элемент с видом Поле индикатора. СтруктураПараметров - понятное дело ваша, там параметры для процедуры, которую будем запускать. Для простоты можно сделать просто процедуру типа
Процедура ДлительнаяОперация(Параметры)
Выполнить(Параметры.Код);
КонецПроцедуры

и на самой форме
СтруктураПараметров = Новый Структура("Код",Код); //Код из реквизита формы

но это совсем упрощенно
13. Xershi 1555 21.10.18 00:24 Сейчас в теме
(12) выход вывод прогресса это не типовой функционал БСП, а нарисованная форма / элемент в обработке. Плюс как я понял нужно делать в логике длительной операции вызов процедуры:
ДлительныеОперации.СообщитьПрогресс(Окр(ПроцентВыполнения, 0), Описание);

В которую и передавать процент выполнения, а далее обработчик ожидания, его прочитает и вставит в наш реквизит.
16. Franchiser 47 31.10.18 12:31 Сейчас в теме
(11) для чего проверяется сообщение на фигурную скобку?
17. Xershi 1555 31.10.18 13:44 Сейчас в теме
(16) когда длительная операция возвращает результат, то он в хмл, вот автор это и проверяет!
14. Franchiser 47 31.10.18 12:13 Сейчас в теме
Если на форме обработки идёт прогресс, у тебя остаются кликабельными кнопки и остаётся возможность менять реквизиты у пользователя в процессе выполнения длительной операции, или ты это запрещаешь?
18. zarankony 311 03.11.18 00:41 Сейчас в теме
(14) менять реквизиты на ходу не получится, только перезапускать сеанс или мутить хранилище со значениями реквизитов и получать их в цикле. Тут надо понимать, что выполнение кода - это уже отдельный сеанс, основной сеанс о нем знает по идентификатору, а второй сеанс о первом не знает впринципе. Как я уже говорил пример где это работает здесь: https://infostart.ru/public/585055/ кода много в итоге, не уверен что Вам все нужно.
20. Franchiser 47 03.11.18 01:32 Сейчас в теме
(18) речь не об этом, я не понимаю почему выбраеа такая технология : размещать прогресс на той же форме, а не открывать отдельную как в бсп.
В этом случае же есть недостатки:
1. Нужно постоянно во все свои доработки вносить намыорму прогресс и код для фонового задания
2. Когда пользователь запустил длительный процесс, он может в форме продолжать что-то творить , т.к. она осталась не заблокированной.

Мне кажется удобнее когда форма прогресса открывактся отдельно с блокированием прогоесса.
P.s. Обработку посмотреть не могу, нет см.
21. zarankony 311 03.11.18 22:50 Сейчас в теме
(20) нет особых проблем с тем чтобы заблокировать форму, это уже по желанию Доступность = ложь; для всех элементов кроме кнопок управления внешним процессом. Вообще идея в том чтобы код можно было вписывать в текстовое поле или например хранить в файлах, то есть обработка одна, а вариантов запускаемого кода много.
15. Franchiser 47 31.10.18 12:15 Сейчас в теме
До конца не понятно какие процедуры используются, т.к. указаны части кода из процедур, можешь привести код всех процедур полностью?
22. compaud 08.11.18 16:44 Сейчас в теме
Что то я не понял что и как нужно сделать.

Я хочу сформировать табличный документ. Каждая строчка которого долго делается.

В одной обработке в модуле объекта я пишу

Процедура ДлительнаяОперация() ЭКСПОРТ
	
	Дата = ТекущаяДата();
	
	Пока Дата <= Дата+60000 Цикл
		Сообщить(ТекущаяДата());
	КонецЦикла;
	
	
КонецПроцедуры
Показать


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

Потом я делаю еще 1 обработку:

&НаКлиенте
Процедура Сформировать(Команда)
	СформироватьнаСервере();	
	
	ПодключитьОбработчикОжидания("ПроверкаФоновогоЗадания",1,Ложь);
	
	
	
КонецПроцедуры


Процедура СформироватьнаСервере()
	
	ПараметрыЗадания = Новый Структура;
	ПараметрыЗадания.Вставить("ИмяОбработки", Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию("ПроверкаСтатусБар"));
	
	
	
	СтруктураПараметров = Новый Структура();//("РезультатЗапроса,Код,Параметры",Результат[Результат.ВГраница()],Код,ПараметрыЗапроса);    
	
	НаименованиеЗадания = НСтр("ru = 'Длительная операция внешней обработки'");
	
	ВыполняемыйМетод = "ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки";
	
	ПараметрыЗадания = Новый Структура;
	ПараметрыЗадания.Вставить("ИмяОбработки", Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию("ПроверкаСтатусБар"));
	ПараметрыЗадания.Вставить("ИмяМетода", "ДлительнаяОперация");
	ПараметрыЗадания.Вставить("ПараметрыВыполнения", СтруктураПараметров);
	ПараметрыЗадания.Вставить("ЭтоВнешняяОбработка", Истина);
	ПараметрыЗадания.Вставить("ДополнительнаяОбработкаСсылка",Неопределено);
	//ПараметрыЗадания.Вставить("ДополнительнаяОбработкаСсылка", Справочники.ДополнительныеОтчетыИОбработки.НайтиПоНаименованию("Длительная операция"));
	
	ПараметрыВыполнения = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
	ПараметрыВыполнения.НаименованиеФоновогоЗадания = НаименованиеЗадания;
	
	РезультатФоновогоЗадания = ДлительныеОперации.ВыполнитьВФоне(ВыполняемыйМетод,ПараметрыЗадания,ПараметрыВыполнения);
	//ЗапуститьВыполнениеВФоне(УникальныйИдентификатор,ВыполняемыйМетод, ПараметрыЗадания, ПараметрыВыполнения);
	
	ИдентификаторЗадания = РезультатФоновогоЗадания.ИдентификаторЗадания;
	
	
	
	
КонецПроцедуры


&НаКлиенте
Процедура ПроверкаФоновогоЗадания()
	
	Результат=ПроверкаФоновогоЗаданияНаСервере();
	Если Результат = Неопределено Тогда
		УбитьПроцесс(Неопределено);
	Иначе
		Если НЕ Результат.Состояние = "Задание выполняется" Тогда
			УбитьПроцесс(Неопределено);
		КонецЕсли;
	КонецЕсли;
	//Состояние("Выполняется алгоритм...",ПрогрессОбработки);
КонецПроцедуры

&НаКлиенте
Процедура УбитьПроцесс(Команда)
	
	УбитьПроцессНаСервере();
	ОтключитьОбработчикОжидания("ПроверкаФоновогоЗадания");
	Сообщить(""+ТекущаяДата()+" задание выполнено");
	
КонецПроцедуры
Функция ПроверкаФоновогоЗаданияНаСервере()
	Рез = Новый Структура("Прогресс,Состояние");
		
	Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
	ЗаполнитьЗначенияСвойств(Рез,Задание);
	Рез.Состояние= СТрока(Рез.Состояние);
	Если Задание = Неопределено Тогда
		Возврат Неопределено;
	Иначе
		
		Сообщения=Задание.ПолучитьСообщенияПользователю(Ложь);
		Для Каждого Сообщение ИЗ Сообщения Цикл
			Если Лев(Сообщение.Текст,1) <> "{" Тогда
				Сообщить(Сообщение.Текст);
			КонецЕсли;
		КонецЦикла;
		Прогресс = ДлительныеОперации.ПрочитатьПрогресс(ИдентификаторЗадания);
		Если Прогресс <> Неопределено Тогда
			ПрогрессОбработки = Прогресс.Процент;//?(Прогресс.Процент<>0,Прогресс.Процент,ПрогрессОбработки);
		КонецЕсли;
		Рез.Вставить("Прогресс",Прогресс);
	КонецЕсли;

	Возврат Рез;
КонецФункции

&НаСервере
Процедура УбитьПроцессНаСервере()
	Задание = ФоновыеЗадания.НайтиПоУникальномуИдентификатору(ИдентификаторЗадания);
	Задание.Отменить();
//	Элементы.ГруппаФоновоеЗадание.Видимость=Ложь;
КонецПроцедуры
Показать


На форме 2 обработки создал реквизит ИдентификаторЗадания типа УникальныйИдентификатор

Ну и ничего не работает.

Какой нибудь пример бы чистый.
И я не понимаю еще вот что, этот код опрашивает 1 раз фоновое задание. О каком статус баре идет речь не пойму. Сложно в общем что то
23. vadim1011985 101 08.11.18 17:03 Сейчас в теме
(22) У Вас дополнительная внешняя обработка ?
24. compaud 09.11.18 09:10 Сейчас в теме
(23) да, в этом и смысл. В одну все поместить так понимаю нельзя. Ну хоть в 2
25. vadim1011985 101 09.11.18 10:01 Сейчас в теме
Почему нельзя ? Все можно . Вам просто надо все сделать правильно.
1) добавить 2 ключевых параметра Идентификатор команды - тип строка и ДополнительнаяОбработкаСсылка с типом Справочник ссылка Дополительные внешние отчеты и обработки
2) в модуле формы создать команду которая будет запускать длительную операцию ( но это не сама длительная операция ) см мой 19 ответ в этой теме процедура ЗагрузитьИЗаписать только надо будет заменит ВыполнитьКомандуВФоне на ДлительныеОперацииКлиент.ВыполнитьКомандуВФоне

3) В модуле объекта пишешь функцию регистрации внешней обработки (сведения о внешней обработке )
И добавляешь процедуру ВыполнитьКоманду ( ИдентификаторКоманды,Параметрывыполнения) - тут могу ошибиться как звучит второй параметр , в которой реализуешь свою длительную операцию

Вот и все
RFP; Xershi; +2 Ответить
26. zarankony 311 09.11.18 12:32 Сейчас в теме
(25) Зачем регистрировать? то есть можно и регистрировать, но идея в том что БСП-шная процедура ДлительныеОперации.ВыполнитьПроцедуруМодуляОбъектаОбработки открывает обработку просто как внешний файл и выполняет экспортную процедуру из её модуля. Команда здесь тоже не нужна, хотя наверное и через неё можно.
27. vadim1011985 101 09.11.18 12:39 Сейчас в теме
(26) я описал типовой механизм вызова длительной операции из внешней обработки как это рекомендует 1с.

Просто не понимаю зачем такие сложности получить обработку - передать на сервер и т.д. и т.п. Если есть внешняя обработка код которой нужно выполнить в фоне то это делается просто

Плюс вам писали про стандартные методы БСП и Вы сказали что Вам не нравится что нет идентификатора задания и котик вам не нравится и хотелось бы получать прогресс , но как я Вам уже отвечал это все решаемо , как раз Ваша статья на ряду с другими на эту тему натолкнула меня на мысль написать свою хотя она повторят то чт оо чем я писал тут выше
28. victor_k 95 30.01.19 02:37 Сейчас в теме
Спасибо! Разобрался, использую
29. EvgenS 22.06.19 17:34 Сейчас в теме
Я то то не так понял или фоновое задание которое будет выполняться должно располагаться в конфигурации, а не в обработке?
30. zarankony 311 24.06.19 09:19 Сейчас в теме
(29)в обратотке, в модуле объекта. В конфигурации должна быть БСП с методом ДлительныеОперации.ЗапуститьВыполнениеВФоне.
32. km_if 21.08.19 21:43 Сейчас в теме
(30)
...
ПараметрыКоманды.Вставить("Каталог", Объект.Каталог);
//ПараметрыКоманды.Вставить("Объект",Объект);
ПараметрыКоманды.Вставить("ТипЗагрузкиДокументов",Объект.ТипЗагрузкиДокументов);
ПараметрыКоманды.Вставить("НачПериода",Объект.НачПериода);
ПараметрыКоманды.вставить("КонПериода",Объект.КонПериода);
...
Можно ли в этих параметрах передавать что то сложнее чем число или сторку? Хотел бы передать ТЗ и КомпановщикНастроек.
33. vadim1011985 101 21.08.19 22:05 Сейчас в теме
(32) что мешает поместить тз во временное хранилище , и через параметры передать адрес
34. km_if 21.08.19 23:49 Сейчас в теме
(33)Насколько понял, создается другой сеанс для длительной операции. Поэтому переменная во временном хранилище, созданном в другом сеансе наверно видна не будет. А передать ее стандартным способом не получается, потому что она не сериализируется.
35. vadim1011985 101 22.08.19 01:47 Сейчас в теме
(34) не очень вас понял - посмотрите в стандартных конфигурациях - там сплошь и всюду так делается.
37. km_if 22.08.19 11:56 Сейчас в теме
(35)Попробывал даже вот так - https://forum.infostart.ru/forum9/topic118827/
В процедуре формы оборачивал нужную переменную в структуру, а потом помещал в хранилище.
При попытке получить переменные в "Процедура ВыполнитьКоманду" из временного хранилища по переданным адресам ничего нет.
38. vadim1011985 101 22.08.19 12:11 Сейчас в теме
(37) Смотрите - основная проблема у вас в том что вы хотите передать то , что не может быть передано с клиента на сервер, ТЗ например таким способом передать можно
39. km_if 22.08.19 16:54 Сейчас в теме
(38) ТЗ через временное хранилище тоже пустая.
Получается варианта два - либо я неправильно передаю, либо это вообще передавать не нужно.
Для чего все это. В модуле объекта внешней обработки я в цикле формирую отчеты (по времени долго), для которых и пытаюсь передать отборы любым способом, и все это пытаюсь передать на сервер для организации длительной обработки. Внешнюю обработку естественно помещаю в "Дополнительные отчеты и обработки".
Как можно обойтись без этого?
36. km_if 22.08.19 09:43 Сейчас в теме
(35) До передачи в ПараметрыКоманды попробывал поместить:

АдресВХранилищеОтборы = ПоместитьВоВременноеХранилище(Объект.Отборы, Новый УникальныйИдентификатор);


Отборы - реквизит объекта внешней обработки, тип "КомпоновщикНастроекКомпоновкиДанных"

"Ошибка при выполнении запроса POST к ресурсу /e1cib/files/9ead0971-78e9-4061-8983-34f3c58b5395:
Переданное значение не может быть помещено во временное хранилище".
40. user1095593 25.09.19 15:36 Сейчас в теме
nikita0832, ты можешь сбросить сам файл обработки? Уже два дня мучаюсь не могу толком разобраться... везде только обрывки кода или разные способы, которые не получается довести до ума... Очень хочу с этим разобраться.
41. zarankony 311 25.09.19 15:40 Сейчас в теме
43. loderunner 24.05.24 09:47 Сейчас в теме
(41) Не сохранилось у Вас примера обработки? Что-то никак не получается запустить, пришлите, пожалуйста.
42. cyborg55 34 23.10.19 16:22 Сейчас в теме
nikita0832, а можно мне тоже пример файла обработки, пжт
Оставьте свое сообщение