Прогресс бар 8.2
>> 22 апреля 2013 г.
В отличии от
8.1 версии, в 8.2 просто взять, и "положить" на форму индикатор
выполнения процесса нельзя. Есть конечно команда Состояние, но и она работает
только в тонком/веб клиенте.
У меня же,
на данный момент, база работает еще в толстом клиенте, а показать пользователю,
что час компьютер не завис, а второй час отрабатывает синхронизацию справочника
со сторонней базой - очень критично.
Долго искать
не пришлось. спасибо infostart. Вот статья, в которой описывается базовый принцип. Но
здесь код предназначен для толстого клиента. Я же взял только первую часть
кода, основной идей которого является вынести почти весь код на сервер и
выполнить посредством фонового задания.
1. Обработчики в форме обработки
&НаКлиенте
Процедура ЗагрузитьВсеДанные(Команда)
Если ОбработчикВыполняется(УникальныйИдентификатор) Тогда
Возврат;
КонецЕсли;
ЗапуститьОбработчик(Истина);
КонецПроцедуры
Необходимо проверить, чтобы обработчика выполнялась только в единственном экземпляре, а то сервер просто "ляжет" от 20-ти фоновых заданий
&НаСервере
Функция ОбработчикВыполняется(УникальныйИдентификатор)
СтатусОбработки = 0;
НайденныеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(Новый Структура("ИмяМетода, Состояние", "ПроцедурыОбменаДанными.ИмпортДанныхПолный", СостояниеФоновогоЗадания.Активно));
Если НайденныеЗадания.Количество() Тогда
СтатусОбработки = 1;
КонецЕсли;
Если Булево(СтатусОбработки) Тогда
Сообщение = Новый СообщениеПользователю;
Сообщение.ИдентификаторНазначения = УникальныйИдентификатор;
Сообщение.Текст = "Сейчас выполняется полная загрузка данных. Попробуйте позже.";
Сообщение.Сообщить();
КонецЕсли;
Возврат СтатусОбработки;
КонецФункции
Далее
инициализируем запуск фонового задания с основным кодом, и подключаем
обработчик, который будет проверять состояние выполнения фонового задания.
&НаКлиенте
Процедура ЗапуститьОбработчик()
Прогресс = 0;
ВыполнитьНаСервере(УникальныйИдентификатор);
ПодключитьОбработчикОжидания("ОбработчикОжидания", 1, Ложь);
КонецПроцедуры
При запуске
фонового задания, передаем ему ключ формы, чтобы в дальнейшем именно для этой
формы получать состояние.
&НаСервереБезКонтекста
Процедура ВыполнитьНаСервере(УникальныйИдентификатор)
//Устанавливаем привилегированный режим, если у пользователя нет административных прав. Запускаем фоновое задания из внешней обработки с помощью метода который доступен в УТ 11.
УстановитьПривилегированныйРежим(Истина);
ЗаданиеПараметры = Новый Массив();
ЗаданиеПараметры.Добавить(УникальныйИдентификатор);
ФоновоеЗадание = ФоновыеЗадания.Выполнить("ПроцедурыОбменаДанными.ИмпортДанныхПолный", ЗаданиеПараметры, УникальныйИдентификатор, "СинхронизацияТоваров");
КонецПроцедуры
Я использовал конечно значение прогресса 101 %, так как обработка данных проходит в три этапа, и нужно, чтобы обработчик ожидания не отключился после выполнения первого.
&НаКлиенте
Процедура ОбработчикОжидания()
//Получаем сообщения от фонового задания и прогресс операции. Если операция закончилась отключаем обработчик ожидания.
ПолучитьПрогрессВыполнения(УникальныйИдентификатор, Прогресс);
Состояние(НСтр("ru = 'Тест прогресс бара'"), Прогресс, НСтр("ru = 'Пустой цикл для тестирования'"));
Если Прогресс = 101 Тогда
Прогресс = 100;
ОтключитьОбработчикОжидания("ОбработчикОжидания");
КонецЕсли;
КонецПроцедуры
Определяем по ключу формы запущенное фоновое задание, и считываем все созданные в нем сообщения на пользователя. Если сообщение не предназначен для формы (пустой идентификатор), значит это значение прогресса, иначе это сообщение пользователю, которое необходимо вывести на экран.
В моем
случае еще существуют маркеры, которые начинаются с точки, которые обозначают
начало нового этапа. Они обнуляют прогресс бар, и выводят новый заголовок.
&НаСервере
Процедура ПолучитьПрогрессВыполнения(УникальныйИдентификатор, Прогресс)
НайденныеЗадания = ФоновыеЗадания.ПолучитьФоновыеЗадания(Новый Структура("Ключ", УникальныйИдентификатор));
Если НайденныеЗадания.Количество() = 0 Тогда Возврат; КонецЕсли;
Задание = НайденныеЗадания[0];
ЗаданиеСостояние = Задание.Состояние;
Если ЗаданиеСостояние = СостояниеФоновогоЗадания.Активно Тогда
МассивСообщений = Задание.ПолучитьСообщенияПользователю(Истина);
Если МассивСообщений = Неопределено Тогда Возврат; КонецЕсли;
Для Каждого Сообщение Из МассивСообщений Цикл
Если Строка(Сообщение.ИдентификаторНазначения) = "00000000-0000-0000-0000-000000000000" Тогда
Прогресс = Число(Сообщение.Текст);
ИначеЕсли Лев(Сообщение.Текст, 1) = "." Тогда
Элементы.Прогресс.Заголовок = "% "+СтрЗаменить(Сообщение.Текст, ".", "");
Прогресс = 0;
Иначе
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(Сообщение.Текст, Сообщение.КлючДанных, Сообщение.Поле, Сообщение.ПутьКДанным);
КонецЕсли;
КонецЦикла;
Иначе
Прогресс = 101;
КонецЕсли;
КонецПроцедуры
2. Обработчики в общем модуле
Этот
обработчик так же можно использовать как метод фонового задания. Но для этого нужно
доработать консоль, так как в привычном исполнении консоль заданий не готова к
выполнению методов с параметрами.
Здесь уже
происходит выполнеие обмен данными.
&НаСервере
Процедура ИмпортДанныхПолный(КлючФормы=Неопределено) Экспорт
ТаблицаДанных = СоздатьТаблицуДанных();
СообщитьПрогрессВыполнения("Загрузка из внешней базы", КлючФормы);
СообщитьПрогрессВыполнения(".Загрузка из внешней базы", КлючФормы);
ЗагрузитьИзВнешнейБазы(ТаблицаДанных);
СообщитьПрогрессВыполнения("Импорт завершен", КлючФормы);
СообщитьПрогрессВыполнения(".Завершено", КлючФормы);
КонецПроцедуры
Ранее
обработка использовала табличную часть, ее пришлось заменить на таблицу (в
оригинали она из 15 различных колонок)
&НаСервере
Функция СоздатьТаблицуДанных()
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("ТМЦ", ОписаниеТипСправочник("Номенклатура"));
Возврат ТаблицаДанных;
КонецФункции
&НаСервере
Функция ОписаниеТипСправочник(ИмяСправочника)
Массив = Новый Массив;
Массив.Очистить();
Массив.Добавить(Тип("СправочникСсылка."+ИмяСправочника));
ОписаниеТиповСпр = Новый ОписаниеТипов(Массив);
Возврат ОписаниеТиповСпр;
КонецФункции
Выполняем цикл обработки
Здесь
основной код удален, чтобы была ясна суть изменения прогресса. Он выдается как
число сообщением пользователю, и в обработчике ожидания распознается как
прогресс и выводится, в моем варианте, в числовое поле.
&НаСервере
Процедура ЗагрузитьИзВнешнейБазы(ТаблицаДанных)
Запрос = БазаДанных.CreateDynaset(ТекстЗапроса, 0);
Ном = 0;
Индикатор1 = 0;
ШагИндикатора = ?(Не Запрос.EOF, Число(Запрос.Fields("RN").Value), 0) /100;
Пока Не Запрос.EOF Цикл
Ном = Ном + 1;
Если Цел(Ном/ШагИндикатора)>Индикатор1 Тогда
Индикатор1 = Окр(Ном/ШагИндикатора);
СообщитьПрогрессВыполнения(Формат(Индикатор1, "ЧН=0; ЧГ="));
КонецЕсли;
НоваяЗапись = ТаблицаДанных.Добавить();
Запрос.MoveNextn(1);
КонецЦикла;
КонецПроцедуры
Финально обработка выглядит следующим образом (у меня кроме прогресса, еще отображает время, но это не существенно). Кнопки блокируются, чтобы не вызывать желание нажимать их каждый пять секунд.
0 коммент.:
Отправить комментарий