|
Прогресс бар при работе с запросом | ☑ | ||
---|---|---|---|---|
0
Azgerd
31.07.13
✎
13:11
|
Есть Процедура &НаСервере, в которой выполняется запрос и обход результата запроса. Как правильно прицепить прогресс бар на цикл обхода.
Есть метод Состояние(<ТекстСообщения>, <Прогресс>,<Пояснение>,Картинка>), но он выполняется только на &Клиенте, вызвать процедуру с сервера на клиенте нельзя, есть ли какой-либо общепринятый метод запуска прогресс бара при работе с результатами запроса? |
|||
1
Maxus43
31.07.13
✎
13:14
|
есть обходные пути, не совсем красивые v8: 1С8.2 прогрессбар при выполнении на сервере
|
|||
2
Maxus43
31.07.13
✎
13:15
|
+ только при переборе конечно, во время выполнения запроса - никак
|
|||
3
Капитан О
31.07.13
✎
13:16
|
общепринято фоновое задание запускать и картинку на клиенте крутить, пока задание работает
|
|||
4
Godofsin
31.07.13
✎
13:21
|
(3) Порно показывать?
|
|||
5
Maxus43
31.07.13
✎
13:22
|
(4) бородатого админа, ковыряющегося в сервере. Чтоб юзер понимал что происходит в данный момент
|
|||
6
Полотенчик
31.07.13
✎
13:25
|
Эффективная индикация в 8.2
http://infostart.ru/public/71407/ |
|||
7
Darklight
31.07.13
✎
13:30
|
(3)100% поддерживаю данное решение!
|
|||
8
Fragster
модератор
31.07.13
✎
13:34
|
(3)(7) а как оно должно работать в файловых базах до 18 (или какого-там) релиза?
|
|||
9
Fragster
модератор
31.07.13
✎
13:42
|
(6) эх, если бы контекст не надо было бы передавать туда-сюда для сохранения прогресса (а хранить на сервере) - затраты на вызов контекста намного меньше.
|
|||
10
Fragster
модератор
31.07.13
✎
13:43
|
на вызов без контекста
|
|||
11
Darklight
31.07.13
✎
13:43
|
(6)Идея хорошая, насколько это вообще доступно в 1С, но в реальных задачах с состояниями сложная, может упереться в объёмы таскаемых туда-сюда данные и в некоторых случаях - вообще не решаемая. Например, выполнение запроса вообще никак нельзя проиндицировать, а пользователю всё равно нужно показывать, что мол процесс идёт - имей терпение ;)
Прогресс бар - это конечно хорошо, но я бы просто остановился на фоновых зданиях с цикличной непрогрессирующей индикацией. Конечно - всё зависит от задач - если в задача в своей массе по про времени выполнения состоит не более чем из двух циклов перебора, где на каждую итерацию цикла уходит не боле секунды - то можно им прогресс бар сделать. Но чаще - это всё же просто долго выполняющиеся запросы. (8)эээ.... ну файловые базы - это вообще особый случай. Он вообще очень плохо распараллеливается. Тут конечно можно поизвращаться - но я не стал бы. Если в файловой базе часто используются процессы, выполняющеся минутами - то имеется все 100% смысла переходить на серверную базу. Хоть бы с на бесплатную SQL-ку. И ещё, фоновые задания появились ещё на 8.1 (если говорить о серверном использовании). И ещё, управляемые формы нужны для тонкого клиента - а им нужен сервер 1С. И ещё - управляемые формы можно и на толстом клиенте юзать - тогда должны работать алгоритмы обновления толстого клиента. |
|||
12
Azgerd
31.07.13
✎
13:51
|
Как не вспомнить с настольгией Fox...
sele z_itog Pb= CreateObject('ProgressBar') _str=0 SCAN _str=_str+1 =PB.ShowBar(100*_str/Recc('z_itog'),'идет расчёт') ВыполняетсяКакоетоДействие ENDSCAN и все дела!!! |
|||
13
Полотенчик
31.07.13
✎
13:54
|
//ДанныеЗапроса - структура с запросом
//ЗаголовокФормы - Заголовок формы индикатора //Результат - возвращает только результат запроса.выполнить(); Функция ВыполнитьЗапросСИндикатором(ДанныеЗапроса,ЗаголовокФормы = Неопределено,КомментарийДействия = Неопределено) Экспорт Перем Результат; Запрос = ДанныеЗапроса.Запрос; Попытка //так как это выполняется только для пакетных запросов то подключим МВ Если Запрос.МенеджерВременныхТаблиц = Неопределено Тогда Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц; КонецЕсли; ИсходныйТекст = Запрос.Текст; ТекстДляОбработки = ИсходныйТекст; ПакетЗапросов = Новый Массив; RegExp = Новый COMОбъект("VBScript.RegExp"); RegExp.IgnoreCase = Истина; RegExp.Global = Истина; RegExp.MultiLine = Истина; RegExp.Pattern = "[^""]//.*$"; ТекстДляОбработки = RegExp.Replace(ТекстДляОбработки, ""); RegExp.MultiLine = False; RegExp.Pattern = "((ВЫБРАТЬ)[^;]*|(УНИЧТОЖИТЬ)[^;]*)"; MC = RegExp.Execute(ТекстДляОбработки); Для Каждого M Из MC Цикл ПакетЗапросов.Добавить(M.Value); КонецЦикла; RegExp.Pattern = "((ПОМЕСТИТЬ)\s+[^;\s]*)"; НомерЗапроса = 1; ФормаИндикации = ПолучитьОбщуюФорму("ХодВыполненияОбработкиДанных"); ФормаИндикации.НаименованиеОбработкиДанных = ?(ЗаголовокФормы = Неопределено,"Обработка данных",ЗаголовокФормы); ФормаИндикации.КомментарийОбработкиДанных = ?(КомментарийДействия = Неопределено,"Выполняется заполнение...",КомментарийДействия); ФормаИндикации.Открыть(); СчетчикЦикла = 0; Для Каждого ТекЗапрос Из ПакетЗапросов Цикл СчетчикЦикла = СчетчикЦикла + 1; #Если ТолстыйКлиентОбычноеПриложение Тогда ОбработкаПрерыванияПользователя(); #КонецЕсли НомерЗапроса = НомерЗапроса + 1; Запрос.Текст = ТекЗапрос; Результат = Запрос.Выполнить(); ФормаИндикации.Значение = СчетчикЦикла / ПакетЗапросов.Количество() * 100; КонецЦикла; ФормаИндикации.Закрыть(); Исключение Результат = Запрос.Выполнить(); КонецПопытки; Возврат Результат; КонецФункции |
|||
14
Darklight
31.07.13
✎
13:56
|
(9)Кстати, ограничено, не очень эффективно, но контекст можно хранить на сервере:
1. В параметрах сеанса 2. Через сохранение значения на сервере во временном хранилище ПоместитьВоВременноеХранилище(<Данные>, <Адрес>) 3. Через кеш возвращаемых значений процедур и функций общих модулей (с постоянном обновляемым входным параметром в виде, скажем UUID'а для хранения получения меняющихся данных) с минимальным (или требуемым) сроком хранения кешированного результата (задаётся в настрйоках кеширования модуля) Последний самый извращённый вариант - но, на мой взгляд, наиболее эффективный. Мы так планируем хранить настройки работы учетной системы, сконфигурированные для конкретного пользователя, чтобы каждый раз не читать их из БД и по не необходимости обновлять (по команде извне). В первую очередь это различные расширенные права и условия проверок, священные с объектами данных и движениями по регистрам. |
|||
15
Azgerd
31.07.13
✎
14:05
|
(3)общепринято фоновое задание запускать и картинку на клиенте крутить, пока задание работает
Гы ! А картинка и так крутится - песочные часы :) чем не картинка. |
|||
16
Darklight
31.07.13
✎
14:08
|
(13)Полезно, но не то :( или предлагаете весь запрос мельчить на кучу мелких частей пакета. А как же оптимизация производительности выполнения. Я, конечно, понимаю, что если рч5еь идёт в индикации, то это скорее всего не связано с массовой параллельный запускаемой обработкой данных типа "проведение документов". И чаще - указанный в данном примере подход нужен как раз только для построения отчетов в режиме "только чтение" и если он и так медленно выполняется, то можно пренебречь замедлением, процентов на 10-20, из-за снижения эффективности построения общих планов выполнения SQL запросов (когда его начнут терроризировать мелкими последовательными запросиками).
|
|||
17
Полотенчик
31.07.13
✎
14:12
|
(16) Зачем специально мельчить? Когда строишь сложный запрос логично разбивать его на временные таблицы. Откройте ЗУП - там бешеные запросы с десятком таблиц...
ps сам я не сталкивался с такими уж долгими запросами, что приходится показывать какую-то индикацию. обычно у меня долгие запросы - rовнокод без учета как работает СУБД. |
|||
18
Полотенчик
31.07.13
✎
14:14
|
+ (17) не в смысле что мои запросы - шлак тормозной, а по работе приходится сталкиваться с разными "художествами"
|
|||
19
Darklight
31.07.13
✎
14:14
|
(15)Надо что-то по больше покрасивее и повнушительнее для душевного спокойствия пользователей. Можно, например,запустить мини прогресс на три деления, циклически повторяемый, а через каждые три повторения (увеличвая каждлйы раз их на три для следующего вывода) ещё и выдавать сообщение пользовтаелю из списка (последовательно):
Ещё выполняется Пока ещё выполняется Нужно подождать - ещё выполоняется Процесс оказалася долгим - ждите Имейте терпение Нужно подождать Ещё немного Ещё чуть чуть Да... процесс затянлся Очень долго, я знаю Ждите-Ждите - процесс идёт ну а далее можно подгрузить свежие анекдоты из anekdot.ru/last/j.html http://www.anekdot.ru/scripts/rand_anekdot.php?t=j и потихоньку начать выводить (построчно) Иногда выводя фразы из списка выше - для разнообразия и напоминания, что это проецесс ещё выполняется, а не просмотр анекдотов. |
|||
20
Darklight
31.07.13
✎
14:16
|
(16)Просто если не мельчит, то эти составные части либо сами в целом будут долго выполняться, либо будет дисбаланс - одни частями будут очень быстрые - а другие медленные - и прогресс бар будет двигаться уж очень урывками - что очень сильно бесит!
|
|||
21
Darklight
31.07.13
✎
14:17
|
(16)(17)Я согласен - в ЗУП просто y.e.бные запросы!
|
|||
22
dmpl
31.07.13
✎
14:18
|
(11) Если у тебя запрос исполняется дольше 5-10 секунд - ты что-то делаешь не так. Прогресс-бар же реально нужен на задачи, выполняемые минутами и часами...
|
|||
23
Darklight
31.07.13
✎
14:27
|
(22)Конечно - не так наши пользователи слишком много вводят данных, и слишком много их выводят, да ещё и за большие сроки. А я пишу запросы, которые выполняются за раз ;)
Но в любом случае - конечно всё зависит от задачи. |
|||
24
Darklight
31.07.13
✎
14:30
|
А выполняющиеся часами вещи - вообще нужно распараллеливать (в инете есть ис таьи на эту тему и готовые решения). И строится это как раз на запуске множества фоновых заданий, с ожиданием их выполнения на клиенте. А раз они так долго выполняются, то их текущие состояния можно периодически и через БД (вспомогательный регистр) передавать на клиент (скажем, раз в минуту - это не будет накладно).
|
|||
25
Azgerd
31.07.13
✎
14:38
|
(11) дык речь идет не о том, за сколько времени выполняется запрос, а о том, сколько может длиться обход результата запроса и действия
в каждом шаге обхода, в запросе может быть всего 100 записей и он выполнится мгновенно, а во время обхода этих записей можно столько наваять, что этот обход будет длиться к примеру минут 10 (что во многих случаях вполне нормально). А за десять минут если на экране нифига не происходит у пользователя может лопнуть терпение... |
|||
26
dmpl
31.07.13
✎
14:41
|
(23) На достаточно большой базе не видел ни одного запроса, который бы обоснованно выполнялся дольше указанного времени. Во всех случаях 5-10-60-минутного выполнения запроса путем приведения запроса к нормальному виду удавалось привести время его исполнения в приемлемые рамки 5-10 с.
|
|||
27
Darklight
31.07.13
✎
14:46
|
(26)Оптимизация - это не тот метод, который пропагандирует наша организация! Да и все предыдущие, где я работал, тоже :(
И куда ты денешься, если нужные данные можно будет достатать лишь... скажем из регистраторов, делая выборку по необходимости "с начала всех времён". Одной перестройкой запроса тут не обойтись. И а изменение сложившейся архитектуры, да ещё если она типовая, да ещё если пользователи за годы набили туда кучу данных и по закрывали периоды.... упаси боже - наши руководители никогда не дадут на это санкции и не выделать на это время! |
|||
28
Darklight
31.07.13
✎
14:59
|
(25)ясно ясно... тут просто тематики смешались - нужно вернуться в русло исходной задачи. Смотри (6), (14), (19).
(6) конечно имеет смысл дорабатывать (см 14), а так же, может применятьт более сложные методики дробления кода, выполняемого на каждой итерации, цикла, с сохранением промежуточных результатов что-то типа такого исходный цикл Функция ОбработкаВсехДанных(Параметры) Состояние = ПолучитьСостояние(Параметры); //Какой-то код получения данных для обработки в цикле Пока Состояние.Данные.Следующий() Цикл //Здесь часть кода 1 //Здесь часть кода 2 //Здесь часть кода 3 КонецЦикла; //Здесь часть завершения всей обработки возврат Результат; КонецФункции функция ОднаИтерация(Параметры) Состояние = ПолучитьСостояние(Параметры); //см (14) - это задача в задаче Если состояние.Часть=1 Тогда Если не Состояние.Данные.Следующий() Тогда //Здесь часть завершения всей обработки возврат Результат; КонецЕсли; //Здесь часть кода 1 состояние.Часть=2 ИначеЕсли состояние.Часть=2 Тогда //Здесь часть кода 2 состояние.Часть=3 ИначеЕсли состояние.Часть=3 Тогда //Здесь часть кода 3 состояние.Часть=1 КонецЕсли; //Код подготовки следующей итерации возврат Параметры.ТекущийСчетчик+1; конецфункции |
|||
29
Darklight
31.07.13
✎
15:06
|
(28)Забыл вставить в конце где "Код подготовки следующей итерации" код сохранения обновлённого состояния (хранящегося на серверном контексте):
СохранитьСостояние(Состояние); Задача по хранению, получению и обновлению состояния данных на серверном контексте - это отдельная задача, лишь косвенно связанная с реализацией прогрессбара. О методах хранения я написал в (14) Да и ещё, конечно код можно усложнить - добавив как в (6) проверку времени и цикл на проведение нескольких итераций, если их обработка окажется короткой, чтобы не выполнение внутри функции ОднаИтерация(Параметры) шло порядка 1-4 секунд, и она сама бы контроллировала объём порции данных, которые готова уложить в расчетные 1-2 секунды своей работы. Универсальный код тут н напишешь - разбиение на части с контролем времени и его оценка - это индивидуальная задача уже из области искусства и конкретного приложения. |
|||
30
Darklight
31.07.13
✎
15:37
|
(12)Кстати, это явно был не тонкий клиент ;) а на толстом вы такое и сейчас сделаете в 1С
|
|||
31
Лефмихалыч
модератор
31.07.13
✎
16:16
|
(0) исходя из того, что с сервера вызвать клиента не возможно, единственное средство - на сервере что-то складывать туда, откуда клиент с некоторой периодичностью может получать инфу о прогрессе. Временное хранилище подойдет.
Только это при любом раскладе - гонять инфу между клиентом и сервером, что не есть гуд |
|||
32
Darklight
31.07.13
✎
16:22
|
(31)А что Вы там такое большое гонять собрались? Число состояния прогресса?.. раз в минуту?
|
|||
33
Лефмихалыч
модератор
31.07.13
✎
16:26
|
(32) я ни чего не собирался, автора спрашивай
|
|||
34
Darklight
31.07.13
✎
16:29
|
(33)Но Вы же написали "Только это при любом раскладе - гонять инфу между клиентом и сервером, что не есть гуд", тем самым высказали своё мнение. Я пытаюсь оценить это мнение.
|
|||
35
Azgerd
31.07.13
✎
16:52
|
(33) В форме есть кнопка, по этой кнопке запускается серверной процедура, где происходит выборка из запроса по определённым условиям документов СчетНаОплатуПокупателям, далее делаем обход этой выборки:
Пока Выборка.Следующий() Цикл Док = Выборка.ССылка.ПолучитьОбъект(); НовыйДок = Док.Скопировать(); НовыйДок.Дата = ЭтаФорма.Дата; ТЧ = НовыйДок.Услуги; Для Каждого Строка Из ТЧ Цикл Строка.Содержание = СокрЛП(Строка.Номенклатура)+" "+СокрЛП(ЭтаФорма.Комент); КонецЦикла; НовыйДок.Записать(); КонецЦикла; Вроде и записей немного (порядка 100) а при выполнении процедуры задумываемся минуты на 2... Вот думал прогресс бар повесить, теперь возникают смутные сомнения... |
|||
36
Darklight
31.07.13
✎
16:55
|
(35)Две минуты - это не срок
Да - а тут такие разговоры со сложными методами решений развели ;) |
|||
37
Azgerd
31.07.13
✎
17:04
|
Хотелось бы иметь какие-то стандартные механизмы для обмена сервера и клиента. Такая же фигня возникает с методом Вопрос() - ну нужно иногда при работе с таблицой спросить у юзера о дальнейших действиях! Ан нет!!! Метод Вопрос() работает только на клиенте и казалось бы простейшее действие заставляет неимоверно изгаляться...
|
|||
38
Конфигуратор1с
31.07.13
✎
17:05
|
||||
39
Darklight
31.07.13
✎
17:05
|
Кстати, ещё одна прикольная мысль в голову пришла, но она специфическая:
СДЕЛАТЬ ВНЕШНЮЮ КОМПОНЕНТУ, которая могла бы соединяться сама с собой по TCP/IP и посылать сигнал через сеть. А в сигнале размещать сообщение с числом прогресса. Тогда обработку стартовать в фоновом задании (от запроса до конца цикла), там же создавать внешнюю компоненту (на сервере) и к ней обращаться, для отправки сигнала. Естественно при вызове нужно будет ещё передать свои идентификационные данные (от компоненты, запущенной на клиенте, чтобы серверная нашла клиентскую). А на клиенте в обработчике получения внешнего сообщения (от клиентской компоненты) или в обработчике ожидания получать из компоненты текущее сообщение о прогрессе и обновлять прогресбар. Заморочено: Да Требует особых навыков программирования: Да Возможны проблемы в настройке сетевого канала: Да Возможны проблемы при VPN/WEB доступе: Да Возмождны проблем в работке компоненты, написанной не на 1С: Да Прогрессивно: Да Технологично: Да Круто: Да Универсально: Да Будете ли вы это делать: Нет А я бы может и заморочился ;) |
|||
40
Darklight
31.07.13
✎
17:07
|
(38)Ну там о секунда речь и о другом - о секундах порой надо думать. О часах надо думать. о минутах - неее
|
|||
41
Лефмихалыч
модератор
31.07.13
✎
17:09
|
(34) отлезь пожалуйста
|
|||
42
Darklight
31.07.13
✎
17:10
|
А кстати говоря ;) я в (14) упоминал в п.2
Читаем из синтаксис помощника ПОСЛЕДНИЙ АБЗАЦ "Примечание" ПоместитьВоВременноеХранилище (PutToTempStorage) Синтаксис: ПоместитьВоВременноеХранилище(<Данные>, <Адрес>) Параметры: <Данные> (обязательный) Тип: Произвольный. Данные, которые необходимо поместить во временное хранилище. <Адрес> (необязательный) Тип: УникальныйИдентификатор; Строка. Адрес во временном хранилище, по которому надо поместить данные. Или уникальный идентификатор формы, во временное хранилище которой, надо поместить данные и вернуть новый адрес. В случае, если передается УникальныйИдентификатор формы, то значение будет автоматически удалено после закрытия этой формы. Если параметр не указан, помещенное значение будет удалено после очередного запроса сервера из общего модуля, при контекстном и неконтекстном серверном вызове из формы, при серверном вызове из модуля команды или при получении формы. Возвращаемое значение: Тип: Строка. Если в параметре <Адрес> указан уникальный идентификатор формы, то после помещения значения во временное хранилище формы, возвращает адрес. Данные возвращаются только после того, как фоновое задание будет завершено. Описание: Сохраняет сериализуемое значение во временное хранилище. Доступность: Тонкий клиент, веб-клиент, сервер, толстый клиент, внешнее соединение. Примечание: Также позволяет поместить данные из фонового задания в родительский сеанс. Для этого следует в родительском сеансе поместить во временное хранилище пустое значение, передав идентификатор формы. Затем полученный адрес передать в фоновое задание через параметры фонового задания. Далее, если этот адрес использовать в параметре <Адрес>, то результат будет скопирован в сеанс, из которого было запущено фоновое задание. |
|||
43
Лефмихалыч
модератор
31.07.13
✎
17:11
|
(37) отличный план спрашивать что-то с сервера у клиента. А если код регламентным заданием вызван, кто ответит? Александр Друзь?..
|
|||
44
Darklight
31.07.13
✎
17:11
|
(41)Ну, вот пошли наезды. Хотя я Вам ничего плохого не говорил. И вы сами "влезли"
|
|||
45
Лефмихалыч
модератор
31.07.13
✎
17:12
|
(44) так это ты ко мне с вопросами приклеился, а не я к тебе
|
|||
46
Darklight
31.07.13
✎
17:23
|
(43)Поддерживаю - это просто не гуд дизайн.
Вот они особенности настоящей клиент-серверной модели. К этому нужно привыкать. И стараться правильно создавать архитектуру решения, учитывающую такие, в общем-то, ключевые особенности данной модели. Нужно разделять алгоритм на части, чередующие между собой интерактивную и обрабатывающую часть. При этом, интерактивную, настоятельно рекомендуется иметь одну-две, ближе к началу (чередуя с обрабатывающей). Так же желательно сразу закладывать "интерактивные ответы по умолчанию", когда код не может быть возвращён пользователю, чтобы использовать их как настройки по умолчанию. Примерно по такому приницыпу я не давно строил систему удалённого файлового хранилища. Нужно было работать с файлами через доступ с Сервера 1С, получая команды как интерактивно от клиента, так и от серверных процессов (например от обмена или подписки на события). Пришлось и интерактивную часть всю отдельно выносить (до начала основного процесса обработки файлов) и реализовывать управляющие алгоритмы, работающие вне интерактивного контура, по заложенным в настройках параметрам по умолчанию. В конце ещё можно было бы сделать финальную интерактивную часть, отложенного действия - когда клиент войдёт в данный контекст - сообщить ему о прошедших операциях и даже спросить подтверждение или изменение в их работе т.е. уже постфактум, с соответствующей переделкой работы. Вот так вот сложновато немного выходит в клиент-серверной архитектуре, но тут другого пути не было. Особенности разграничения доступности файловых ресурсов - доступ к хранилищу только у сервера. И я как раз там использовал функцию ПоместитьВоВременноеХранилище() (45)Мне было интересно, ладно, забудем! |
Форум | Правила | Описание | Объявления | Секции | Поиск | Книга знаний | Вики-миста |