Главная » Статьи » "1С" Програмирование

Скачивать материалы с сайта, могут только зарегистрированные пользователи.
Для регистрации заполните два поля ниже!

Через минуту Вы получите "Гостевой доступ"




Правильная индикация прогресса цикла
Правильная индикация прогресса цикла
  
Работу некоторых циклов с большим количеством проходов разумно сопровождать индикацией прогресса. Но зачастую сама эта индикация и становится главным тормозом процесса. Так как частенько на практике встречаю подобные огрехи, решил опубликовать пример правильной индикации.
 
Так как индикатор представляет собой элемент графического интерфейса пользователя, то любая операция с ним выполняется относительно долго, будь то строка состояния, индикатор или даже надпись. Поэтому в случае большого количества проходов цикла обновление индикатора на каждом проходе может стать главным потребителем вычислительных ресурсов компьютера. Хотя такие ситуации легко обнаруживаются с помощью замера производительности, все же лучше сразу предусматривать подобные проблемы.

Привожу 2 вспомогательных метода, которые позволят просто и эффективно реализовать индикацию любого цикла с известным максимальным значением счетчика.
 

// Получает структуру для индикации прогресса цикла.
//
// Параметры:
// КоличествоПроходов – Число - максимальное значение счетчика;
// ПредставлениеПроцесса – Строка, "Выполнено" – отображаемое название процесса;
// ВнутреннийСчетчик - Булево, *Истина - использовать внутренний счетчик с начальным значением 1,
// иначе нужно будет передавать значение счетчика при каждом вызове обновления индикатора;
// КоличествоОбновлений - Число, *100 - всего количество обновлений индикатора;
// ЛиВыводитьВремя - Булево, *Истина - выводить приблизительное время до окончания процесса;
// РазрешитьПрерывание - Булево, *Истина - разрешает пользователю прерывать процесс.
//
// Возвращаемое значение:
// Структура - которую потом нужно будет передавать в метод ЛксОбработатьИндикатор.
//
Функция ЛксПолучитьИндикаторПроцесса(КоличествоПроходов, ПредставлениеПроцесса = "Выполнено", ВнутреннийСчетчик = Истина,
 КоличествоОбновлений = 100, ЛиВыводитьВремя = Истина, РазрешитьПрерывание = Истина) Экспорт 

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

КонецФункции // ЛксПолучитьИндикаторПроцесса()

// Проверяет и обновляет индикатор. Нужно вызывать на каждом проходе индицируемого цикла.
//
// Параметры:
// Индикатор – Структура – индикатора, полученная методом ЛксПолучитьИндикаторПроцесса;
// Счетчик – Число – внешний счетчик цикла, используется при ВнутреннийСчетчик = Ложь.
//
Процедура ЛксОбработатьИндикатор(Индикатор, Счетчик = 0) Экспорт 

 Если Индикатор.ВнутреннийСчетчик Тогда
  Индикатор.Счетчик = Индикатор.Счетчик + 1;
  Счетчик = Индикатор.Счетчик;
 КонецЕсли;
 Если Индикатор.РазрешитьПрерывание Тогда
  ОбработкаПрерыванияПользователя();
 КонецЕсли;
 Если Счетчик > Индикатор.СледующийСчетчик Тогда
  Индикатор.СледующийСчетчик = Цел(Счетчик + Индикатор.Шаг);
  Если Индикатор.ЛиВыводитьВремя Тогда
  ПрошлоВремени = ТекущаяДата() - Индикатор.ДатаНачалаПроцесса;
  Осталось = ПрошлоВремени * (Индикатор.КоличествоПроходов / Счетчик - 1);
  Часов = Цел(Осталось / 3600);
  Осталось = Осталось - (Часов * 3600);
  Минут = Цел(Осталось / 60);
  Секунд = Цел(Цел(Осталось - (Минут * 60)));
  ОсталосьВремени = Формат(Часов, "ЧЦ=2; ЧН=00; ЧВН=") + ":" 
  + Формат(Минут, "ЧЦ=2; ЧН=00; ЧВН=") + ":" 
  + Формат(Секунд, "ЧЦ=2; ЧН=00; ЧВН=");
  ТекстОсталось = "Осталось: ~" + ОсталосьВремени;
  Иначе
  ТекстОсталось = "";
  КонецЕсли;
ТекстСостояния = Индикатор.ПредставлениеПроцесса + " "
+ Формат(Счетчик / Индикатор.КоличествоПроходов * 100, "ЧЦ=3; ЧДЦ=0") + "% " + ТекстОсталось;

  Состояние(ТекстСостояния);
 КонецЕсли;
 Если Счетчик = Индикатор.КоличествоПроходов Тогда
  Состояние("");
 КонецЕсли;

КонецПроцедуры // ЛксОбработатьИндикатор()

Ключевым моментом в ЛксОбработатьИндикатор() является количество обновлений индикатора (оно ограничено сверху КоличествоОбновлений=100).

Вот пример их использования.

КоличествоДанных = 100000;
Индикатор = ЛксПолучитьИндикаторПроцесса(КоличествоДанных, "Проверка данных");
Для Счетчик = 1 По КоличествоДанных Цикл
ЛксОбработатьИндикатор(Индикатор, Счетчик);
КонецЦикла;

КоличествоДанных = 100000;
Индикатор = ЛксПолучитьИндикаторПроцесса(КоличествоДанных, "Проверка данных", Истина);
Для Счетчик = 1 По КоличествоДанных Цикл
ЛксОбработатьИндикатор(Индикатор);
КонецЦикла;


Вот как это выглядит визуально
Категория: "1С" Програмирование | Добавил: c1 (2009 Февраль 21)
Просмотров: 2057 | Комментарии: 1 | Теги: Правильная индикация прогресса цикл | Рейтинг: 0.0/0

Выразить благодарность - Поделиться с друзьями!

 

Здесь все о технической стороне 1С!

 

Узнай, как правильно администрировать 1С Предприятие
Регистрируйся на бесплатный 7-ми дневный курс сейчас:

Ваш E-Mail в безопасности



Всего комментариев: 1
avatar
1
Бывают в жизни огорченья sad
Но это не тот случай biggrin
avatar