Своя индикация длительной операции во внешней обработке

Программирование - Практика программирования

Дополнительная обработка индикация процесса фоновое задание

9
Описан способ организации собственной индикации длительной операции для внешних обработок для БСП версии 2.4 и выше

Всех привет !! 

В данной статье пойдет речь о индикации длительных операций во внешней обработке. Хотя таких статей уже много ,решил добавить еще одну так как описанный здесь метод мне еще не попадался (возможно где-то и есть), может кому-то пригодится. Необходима версия БСП 2.4 и выше. 

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

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

Если внимательно посмотреть код запуска длительной операции для дополнительной обработки (Общий модуль ДополнительныйОтчетыИОбработкиКлиент.ВыполнитьКомандуВФоне) , то там можно увидеть следующее

Процедура ВыполнитьКомандуВФоне(Знач ИдентификаторКоманды, Знач ПараметрыКоманды, Знач Обработчик)   

   .....
   ..... 
    НастройкиОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(Форма);
	НастройкиОжидания.ТекстСообщения       = СопровождающийТекст;
	НастройкиОжидания.ВыводитьОкноОжидания = Истина;
	НастройкиОжидания.ПолучатьРезультат    = ПолучатьРезультат; // для обратной совместимости
	НастройкиОжидания.ВыводитьСообщения    = Истина;
	
	ДлительныеОперацииКлиент.ОжидатьЗавершение(Задание, Обработчик, НастройкиОжидания);

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

Тут нас интересует структура НастройкиОжидания. Она получается функцией из общего модуля  ДлительныеОперацииКлиент.ПарметрыОжидания (). Вот ее код : 

// Возвращает пустую структуру для параметра ПараметрыОжидания процедуры ДлительныеОперацииКлиент.ОжидатьЗавершение.
//
// Параметры:
//  ФормаВладелец - УправляемаяФорма, Неопределено - форма, из которой вызывается длительная операция.
//
// Возвращаемое значение:
//  Структура              - параметры выполнения задания: 
//   * ФормаВладелец          - УправляемаяФорма, Неопределено - форма, из которой вызывается длительная операция.
//   * ТекстСообщения         - Строка - текст сообщения, выводимый на форме ожидания.
//                                       Если не задан, то выводится "Пожалуйста, подождите...".
//   * ВыводитьОкноОжидания   - Булево - если Истина, то открыть окно ожидания с визуальной индикацией длительной операции. 
//                                       Если используется собственный механизм индикации, то следует указать Ложь.
//   * ВыводитьПрогрессВыполнения - Булево - выводить прогресс выполнения в процентах на форме ожидания.
//   * ОповещениеОПрогрессеВыполнения - ОписаниеОповещения - оповещение, которое периодически вызывается при 
//                                      проверке готовности фонового задания. Параметры процедуры-обработчика оповещения:
//     ** Прогресс - Структура, Неопределено - структура со свойствами или Неопределено, если задание было отменено. Свойства: 
//	     *** Статус               - Строка - "Выполняется", если задание еще не завершилось;
//                                           "Выполнено", если задание было успешно выполнено;
//	                                         "Ошибка", если задание завершено с ошибкой;
//                                           "Отменено", если задание отменено пользователем или администратором.
//	     *** ИдентификаторЗадания - УникальныйИдентификатор - идентификатор запущенного фонового задания.
//	     *** Прогресс             - Структура, Неопределено - результат функции ДлительныеОперации.ПрочитатьПрогресс, 
//                                                            если ВыводитьПрогрессВыполнения = Истина.
//	     *** Сообщения            - ФиксированныйМассив, Неопределено - если ВыводитьСообщения = Истина, массив объектов СообщениеПользователю, 
//                                  очередная порция сообщений, сформированных в процедуре-обработчике длительной операции.
//     ** ДополнительныеПараметры - Произвольный - произвольные данные, переданные в описании оповещения. 
//
//   * ВыводитьСообщения      - Булево - выводить в оповещения о завершении и прогресс сообщения, 
//                                       сформированные в процедуре-обработчике длительной операции.
//   * Интервал               - Число  - интервал в секундах между проверками готовности длительной операции.
//                                       По умолчанию 0 - после каждой проверки интервал увеличивается с 1 до 15 секунд
//                                       с коэффициентом 1.4.
//   * ОповещениеПользователя - Структура - содержит свойства:
//     ** Показать            - Булево - если Истина, то по завершении длительной операции вывести оповещение пользователя.
//     ** Текст               - Строка - текст оповещения пользователя.
//     ** НавигационнаяСсылка - Строка - навигационная ссылка оповещения пользователя.
//     ** Пояснение           - Строка - пояснение оповещения пользователя.
//   
//   * ПолучатьРезультат - Булево - Служебный параметр. Не предназначен для использования.
//
Функция ПараметрыОжидания(ФормаВладелец) Экспорт
	
	Результат = Новый Структура;
	Результат.Вставить("ФормаВладелец", ФормаВладелец);
	Результат.Вставить("ТекстСообщения", "");
	Результат.Вставить("ВыводитьОкноОжидания", Истина);
	Результат.Вставить("ВыводитьПрогрессВыполнения", Ложь);
	Результат.Вставить("ОповещениеОПрогрессеВыполнения", Неопределено);
	Результат.Вставить("ВыводитьСообщения", Ложь);
	Результат.Вставить("Интервал", 0);
	Результат.Вставить("ПолучатьРезультат", Ложь);
	
	ОповещениеПользователя = Новый Структура;
	ОповещениеПользователя.Вставить("Показать", Ложь);
	ОповещениеПользователя.Вставить("Текст", Неопределено);
	ОповещениеПользователя.Вставить("НавигационнаяСсылка", Неопределено);
	ОповещениеПользователя.Вставить("Пояснение", Неопределено);
	Результат.Вставить("ОповещениеПользователя", ОповещениеПользователя);
	
	Возврат Результат;
	
КонецФункции

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

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

К сожалению, по умолчанию,  для дополнительных обработок предусмотрен только вывод окна с котиком (за это отвечает поле ВыводитьОкноОжидания структуры НастройкиОжидания ) , поэтому для изменения механизма оповещения необходимо скопировать метод общего модуля ДополнительныйОтчетыИОбработкиКлиент.ВыполнитьКомандуВФоне к себе в обработку в модуль формы и сделать нужные изменения 

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

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

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

Осталось только написать свою процедуру обработки процесса выполнения я например сделал так 

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

        
   Если Результат.Статус = "Выполняется" или Результат.Статус = "Выполнено" Тогда
                 
         Прогресс = Результат.Прогресс;
	 
	  
          Если Прогресс <> Неопределено Тогда  
			  
			  Индикатор = Прогресс.Процент; // Индикатор - полей Индикатор на форме
			  ТекстСопровождения = Прогресс.Текст; // поле надпись на форме
			  
		 КонецЕсли;
		 
    
   КонецЕсли;
	

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

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

9

Скачать файлы

Наименование Файл Версия Размер
Шаблон внешней обработки с возможностью реализации собственной индикации процесса
.epf 7,80Kb
04.11.18
3
.epf 7,80Kb 3 Скачать

См. также

Комментарии
Избранное Подписка Сортировка: Древо
1. herfis 264 05.11.18 10:16 Сейчас в теме
А БСП 2.4 зачем? Что они там опять поменяли?
Я аналогичную фигню для 2.2/2.3 делал, причем без копирования общих модулей и допилок. Правда давно было, подробностей уже не помню :)
2. vadim1011985 56 05.11.18 11:07 Сейчас в теме
(1) Если честно не сильно вникал что там поменялось (просто смутило то что на its.1c для версия БСП 2.3 и БСП 2.4 немного по разному было описан механизм запуска фоновых заданий для дополнительных обработок), возможно и для БСП 2.3 будет работать , на счет копирования - копируется всего одна функция общего модуля к себе в обработку , дописывается 2 строчки и пишется процедура обработчик прогресса и все - не надо думать как передать результат с сервера на клиент , как как получить фоновое задание для проверки,его выполнения, на нужно писать подключаемые обработчики для проверки выполнения фонового задания или для считывания прогресса - все это уже реализовано.
По мне так это очень простой и эффектный способ решения , ради которого можно потратить 2 минуты (или меньше) своего времени и скопировать процедуру к себе в обработку.
3. herfis 264 05.11.18 11:46 Сейчас в теме
(2) Согласен. Усилий минимальное количество. Плюсанул.
12. Franchiser 74 10.11.18 20:27 Сейчас в теме
(2) не понял из статьи: на основании чего рассчитывается прогресс, откуда известно сколько данных в выборке будет обработано в фоновом задании? Нужно как-то описывать расчет прогресса?
13. vadim1011985 56 10.11.18 21:55 Сейчас в теме
(12) Да, подсчет прогресса вы организовываете сами при выполнении длительной операции . В модуле объекта обработки должны быть процедура ВыполнитьКоманду в который Вы описываете ваш алгоритм длительной операции (например создание документов по данным из файлов ) и в любом месте Вы можете вызвать метод ДлительныеОперации.СообщитьПрогресс где будуту передавать прогресс выполнения либо текст например так

Процедура ВыполнитьКоманду(ИдентификаторКоманды,ПараметрыВыполнения) Экспорт
	
	ДлительныеОперации.СообщитьПрогресс(5,"Начало загрузки");
	
	ТабЗагрузки.Очистить();
	НайденныеФайлы = НайтиФайлы(ПараметрыВыполнения.Каталог,"*.csv",);
	
	 Обработано = 0;
	
		Для каждого ТекФайл Из НайденныеФайлы Цикл
			
		
			ТекстСопровождения = "Обработано "+Обработано+ " из "+НайденныеФайлы.Количество();
			
			ПроцентОбработки = Цел(Обработано/НайденныеФайлы.Количество()*100);
			
			ДлительныеОперации.СообщитьПрогресс(ПроцентОбработки,ТекстСопровождения); 
			ПрочитатьФайл(ТекФайл.ПолноеИмя,ПроцентОбработки);
		КонецЦикла;
		
КонецПроцедуры

Процедура ПрочитатьФайл(ТекИмяФайла,ТекущийПроцент) Экспорт
....
....
.....

ТекстСообщения = "Читаем файл  "+ ТекИмяФайла;

ДлительныеОперации.СообщитьПрогресс(ТекущийПроцент, ТекИмяФайла);
КонецПроцедуры

Показать
Franchiser; +1 Ответить
14. Franchiser 74 11.11.18 15:56 Сейчас в теме
4. Xershi 403 05.11.18 11:51 Сейчас в теме
Отличная статья, чуть раньше разбирался по https://infostart.ru/public/842660/.
Но автор опустил много подробностей, которые существенно влияют на разработку.
Как я там комментировал, то прогресс через БСП не реализуется. Нужна своя индикация в виде элементов или можно передавать в процедуру состояние.
5. vadim1011985 56 05.11.18 12:01 Сейчас в теме
(4) Указал ссылку на мою же статью )))
6. Xershi 403 05.11.18 12:04 Сейчас в теме
(5) не смотрел на автора. А для чего было дублировать статью?) Я думаю стоит указать там ссылку на шаблон!
7. vadim1011985 56 05.11.18 12:05 Сейчас в теме
(6) нет, ты не понял ты указал ссылку на ЭТУ статью
8. Xershi 403 05.11.18 12:11 Сейчас в теме
9. vadim1011985 56 05.11.18 13:32 Сейчас в теме
(4)
то прогресс через БСП не реализуется. Нужна своя индикация в виде элементов или можно передавать в процедуру состояние.


Опять же , если смотреть в типовой конфигурации , там тоже проценты прогресс выводится через элементы формы
10. Xershi 403 05.11.18 13:38 Сейчас в теме
(9) есть форма прогресса без процентов, с кружочком, туда можно запихнуть статический текст и кружок будет крутиться. А прогресс отдельно на форме что ли будет выводиться в типовом варианте? Это через сообщить прогресс?
11. vadim1011985 56 05.11.18 13:58 Сейчас в теме
(10) Нет , имеется ввиду что на форме просто размещается поле Индикатор в котором выводится прогресс, для примера можно посмотреть типовую обработку - ВыполнениеОбменаДанными. т.е. сами 1с-ки используют элементы формы для отображения прогресса, по сути это и есть БСП с помощью СообшитьПрогресс передать информацию о ходе выполнения операции и графически отобразить ее с помощью поля индикатор
Прикрепленные файлы:
A_Max; Xershi; +2 Ответить
Оставьте свое сообщение