Технологии Blogger.

Прогресс бар 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);
 
    КонецЦикла;
 
КонецПроцедуры    
 


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



 

Отправить комментарий

  © Blogger template Simple n' Sweet by Ourblogtemplates.com 2009

Back to TOP