gifts2017

Обработка на сервере с индикатором (упр. приложение)

Опубликовал Анатолий Ситников (acsent) в раздел Программирование - Работа с интерфейсом

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

&НаСервере
Функция ИнициализацияОбработкиСервер()

   
Запрос = Новый Запрос;
   
Запрос.Текст =
   
"ВЫБРАТЬ
    |   Спр.Ссылка
    |ИЗ
    |   Справочник.Банки КАК Спр"
;

   
Данные      = Запрос.Выполнить().Выгрузить();
   
АдресДанных = ПоместитьВоВременноеХранилище(Данные, УникальныйИдентификатор);

 
  // Обработка
    // В справочнике ~ 4000 элементов

    Возврат Данные.Количество();

КонецФункции

&НаСервереБезКонтекста
Функция ОбработатьЭлемент(ДанныеЭлемента)

   
СпрОбъект = ДанныеЭлемента.Ссылка.ПолучитьОбъект();

   
// Обработка

   
СпрОбъект.ОбменДанными.Загрузка = Истина;
   
СпрОбъект.Записать();

КонецФункции

&НаСервереБезКонтекста
Функция ОбработатьПорциюНаСервере(Начало, Конец, АдресДанных)

   
Данные = ПолучитьИзВременногоХранилища(АдресДанных);

    Для
Счетчик = Начало - 1 По Конец - 1 Цикл

       
ОбработатьЭлемент(Данные[Счетчик]);

    КонецЦикла;

КонецФункции

&НаКлиенте
Процедура ВыполнитьОбработку(Команда)

   
Количество      = ИнициализацияОбработкиСервер();
   
РазмерШага      = 10;
   
КоличествоШагов = Цел(Количество / РазмерШага);
   
КоличествоЦел   = КоличествоШагов * РазмерШага;

    Если
КоличествоЦел < Количество Тогда
       
Элементы.Индикатор.МаксимальноеЗначение = КоличествоШагов + 1;
    Иначе
       
Элементы.Индикатор.МаксимальноеЗначение = КоличествоШагов;
    КонецЕсли;

    Для
Счетчик = 1 По КоличествоШагов Цикл

       
ОбработатьПорциюНаСервере(РазмерШага * (Счетчик - 1) + 1, РазмерШага * Счетчик, АдресДанных);
       
Индикатор = Счетчик;
       
ОбработкаПрерыванияПользователя();
       
ОбновитьОтображениеДанных();

    КонецЦикла;

    Если
КоличествоЦел < Количество Тогда

       
ОбработатьПорциюНаСервере(КоличествоШагов * РазмерШага + 1, Количество, АдресДанных);
       
Индикатор = Индикатор + 1;

    КонецЕсли;

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

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

Наименование Файл Версия Размер Кол. Скачив.
ОбработкаНаСервереСИндикатором83.epf
.epf 7,84Kb
05.04.16
30
.epf 7,84Kb 30 Скачать
ОбработкаНаСервереСИндикатором.epf
.epf 7,26Kb
05.04.16
314
.epf 7,26Kb 314 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Анатолий Ситников (acsent) 30.09.10 17:44
Думал, что самая затратная прцедура будет
Данные = ПолучитьИзВременногоХранилища(АдресДанных);

а оказалось, вызов сервера куда более затратен
2. Евгений Люлюк (Evg-Lylyk) 01.10.10 17:18
Приблизительно о том же писал здесь http://infostart.ru/public/71407/
3. Анатолий Ситников (acsent) 01.10.10 17:22
Основная фишка в том, чтобы получить выборку данных на сервере и не передавать ее на клиент
4. Евгений Люлюк (Evg-Lylyk) 01.10.10 18:00
(3) Согласен это важно. Разумно осуществлять индикацию раз в секунду тогда будет меньше вызовов сервера... упростится код
5. Никита (Mopo3) 07.06.11 19:02
Имх лучше из клиента вызывать обработчик ожидания каждую секунду, который читает из временного хранилища счетчик итераций обработки. Счетчик итераций во временном хранилище обновляет сам обработчик данных. Зная общее количество состояние вывести просто.
Krio2; leonidol; yandextesting; ll13; +4 1 Ответить 3
6. Юрий Зайцев (Yury1001) 03.05.12 12:24
Отлично работает с выборкой результата запроса – ничего не сбивается.
Вызов сервера действительно затратный по времени, если делить это тысячи раз, будет ощутимо, и потому можно реализовать возврат по таймеру, ну там раз в 3 секунды, например.
7. Денис (Den_D) 06.06.12 10:13
Мне кажется к данной проблеме нет однозначного подхода и универсального решения.
Однако какие-то решения в определенных условиях являются лучшими.
8. Сергей Борисов (juntatalor) 08.07.13 02:16
Раньше реализовывал индикацию данных также, как у вас.

Плюсы: точность отображения, легкий вывод сообщений на сервере, общее удобство

Минусы:
Первый и самый важный: Запрос.Выполнить.Выгрузить(). Для больших объемов данных это весьма затратно по временным ресурсам, по объему "отжираемой" памяти. Еще хуже, когда запрос содержит итоги, и нужно, например, выводить данные с группировками (т.е. для таблицы значений вы можете запомнить "текущую" строку, а для дерева - нет, и его все равно приходится переводить в таблицу значений). Это сильно усложняет код, делает его менее понятным и читаемым. Также достаточно велик трафик обмена клиент-сервер.

Сейчас перевел на работу в фоновых заданиях. У них тоже есть свои минусы: запускаются дольше, сложнее получать из них информацию, сложнее отладка, степень индикации не очень точна. Однако, там можно использовать Запрос.Выполнить().Выбрать(), да и в целом чисто "серверный" код без "дерганий" клиент<->сервер работает быстрее.

И насчет Данные = ПолучитьИзВременногоХранилища(АдресДанных) - они скорее всего кешируются в памяти, поэтому и вызов быстрый.
9. Александр Лучший (KillerMann) 12.02.14 12:14
(5) Mopo3, идея у автора хорошая. А вот Вашу не поддерживаю. Каким образом отработает обработчик ожидания на клиенте если на серверной части будет крутиться процедура(функция) обработки результата запроса? Если знаете решение, то пример в студию, только заведомо рабочий. А пока минус за ответ, т.к. считаю ответ вводящий в заблуждение.
10. Анатолий Ситников (acsent) 12.02.14 12:23
(5) Чтоб подключить обработчик нужно запускать фоновое задание. А чтоб его запускать нужно изменять конфигурацию
11. Александр Лучший (KillerMann) 12.02.14 12:49
(10) acsent, на сколько я понял Mopo3 имел ввиду ПодключитьОбработчикОжидания() в модуле формы, а обработка ожидания не отработает пока не выполнится процедура(функция) на сервере. Или я чего-то не знаю? Речь та не шла за регламентные задания. Если есть решение для не типовой конфигурации и так чтобы можно было воспользоваться методом ПодключитьОбработчикОжидания(), то прошу поподробней описать, в жизни пригодится.
12. Гоша * (E_x) 25.03.14 10:49
Благодарю пользователя, это то, что надо. Немного адаптировал под работу со стандартным методом Состояние() и вообще огонь. Еще раз спасибо!
13. Борис Разорёнов (Bor_ka) 20.10.15 23:09
Попробовал, отлично работает. Спасибо автору.
14. Костя С (doom2good) 10.11.15 11:55
(5) Mopo3,
Не подскажете, как реализовать через ПодключитьОбработчикОжидания()?
в моем варианте
Процедура ВыполнитьОбработку(Команда)
	
	ПодготовитьДанныеСервер();
	МаксимальноеЗначение = КоличествоДанныхВХранилище();
	
	ПодключитьОбработчикОжидания("ОбновитьСтатус", 1);
	ПодключитьОбработчикОжидания("ОбработатьДокументы", 1, Истина);

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


&НаКлиенте
Процедура ОбновитьСтатус()

	ОстатокЭлементов = КоличествоДанныхВХранилище();
	ВсегоЭлементов = МаксимальноеЗначение;
	
	Состояние("Обработка документов", 100 - ОстатокЭлементов /(ВсегоЭлементов/100), "Документы обрабатываются...");
	
	Если ОстатокЭлементов = 0 Тогда
	
		ОтключитьОбработчикОжидания("ОбновитьСтатус");
		Предупреждение("Обработка завершена!");
	
	КонецЕсли;

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


&НаКлиенте
Процедура ОбработатьДокументы()

	ОбработатьДокументыСервер(АдресХранилищаДанных, АдресХранилищаКоличества);

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

&НаСервереБезКонтекста
Процедура ОбработатьДокументыСервер(АдресХранилищаДанных, АдресХранилищаКоличества)

	НепроведенныеДокументы = ПолучитьИзВременногоХранилища(АдресХранилищаДанных);
	
	ВсегоДокументов = НепроведенныеДокументы.Количество();
	
	Для Каждого цДокумент Из НепроведенныеДокументы Цикл
		
		обработатьДокумент(цДокумент);
		
		ВсегоДокументов = ВсегоДокументов - 1;
		ПоместитьВоВременноеХранилище(ВсегоДокументов, АдресХранилищаКоличества);
		
	КонецЦикла;

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


В этом случае у меня появляется индикатор, но выполнение уходит на сервер и после выполнения индикатор перескакивает с 0% сразу на 100%.
15. Илья Вильчик (TreeDogNight) 08.07.16 06:33
(14) doom2good, Меня тоже интересует этот вопрос.Ещё не нашли решение?
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа