Страница 1 из 2
					
				Запуск долгой SP
				Добавлено: 19 Апрель 2015, 23:37
				 ingasoftplus
				Есть у нас Stored Procedure, надо запустить ее из программы на Кларе. Не проблема. 
Проблема в том, что SP может долго работать - 5-10-...30 минут.  И как быть? Как взаимодействовать с юзером?  Сейчас программа как-будто подвисает, пока СП не отработает.  Как лучше сделать?
			 
			
					
				Запуск долгой SP
				Добавлено: 20 Апрель 2015, 1:06
				 Дед Пахом
				запускать её в отдельном потоке.
			 
			
					
				Запуск долгой SP
				Добавлено: 20 Апрель 2015, 10:39
				 kreator
				Если эта Stored Procedure не связана с действиями пользователя, то можно поставить запуск на расписание самими серваком, или чем-то другим. А если связана, то нужно отображать ход процесса, иначе плохо. Отдельный поток может не прокатить, процесс займёт все ресурсы компа, и всё равно в другом окне программы (в другом потоке) работать не получится.
			 
			
					
				Запуск долгой SP
				Добавлено: 20 Апрель 2015, 18:08
				 ingasoftplus
				связана! нужно отображать ход процесса - хотя СП никакого фидбека не дает, пока не закончит работать.  Что показывать юзеру чтоб он не волновался???
			 
			
					
				Запуск долгой SP
				Добавлено: 20 Апрель 2015, 23:52
				 Aragorn
				Можно использовать асинхронное выполнение процедуры, а на время работы прогресс бар запустить с бесконечным циклом (т.е. как 100% набежит, так в обратку с шагом -1 до нуля, и т.д.
А можно гифку показывать  
  
 
			 
			
					
				Запуск долгой SP
				Добавлено: 21 Апрель 2015, 0:18
				 ingasoftplus
				идея хорошая. но как узнать, что процедура еще работает или уже отработала?
file{prop:sql} = 'exec SP....'
и что дальше?  можно конкретики? код, например,  

 
			 
			
					
				Запуск долгой SP
				Добавлено: 21 Апрель 2015, 0:40
				 Aragorn
				А если 
Код: Выделить всё
 
Comm &cCommand
dumm &cCWAdo
Hr HResult
Cmd String(255)
Comm &= new(cCommand)
Cmd = 'exec dbo.pr_Proc'
Comm.SetConnection(Conn1)
Hr = Comm.Init()
Hr = Comm.putcommand( Cmd)
dumm &= Comm._execute(, Hr)
if Hr != s_ok then dumm.showerror(Cmd) end
 
пардон писал с мобильника спля одним глазом и на память. Явно что-то наврал и ошибся, но гдето перед путкоммандом надо выставить свойства executeoptions типа adasyncexecute а как ловить окончание пока не знаю. все. засыпаю...
 
			 
			
					
				Запуск долгой SP
				Добавлено: 21 Апрель 2015, 10:47
				 kreator
				ingasoftplus писал(а):идея хорошая. но как узнать, что процедура еще работает или уже отработала?
Например, вариант такой. Сделать хранимку, которая возвращает что-нибудь. Тогда так:
file{prop:sql} = 'exec SP....'
next(file)
if file.id=1
  "выполнено удачно"
else
  "выполнено с ошибкой"
end
В таком варианте, я так понимаю, программа будет ждать отработки next и будет как бы висеть. Самый простой вариант - перевести курсор в часы до вызова хранимки. Не простой вариант - заставить хранимку писать промежуточный результат, например, во временную таблицу и считывать в программе.
Посмотри ещё свойство PROP:SQLRowSet, о том же.
 
			 
			
					
				Запуск долгой SP
				Добавлено: 21 Апрель 2015, 12:15
				 Shur
				Что если так:
- Основная хр. пр-ра что-нибудь своевременно пишет во вспомогательную таблицу, например шаг, на котором она находится (или количество записей в итоговом датасете).
- Вспомогательная хр.пр-ра читает из этой таблицы текущий шаг и отображает это в окне ползунком или ещё как-нибудь.
- Основная хр. пр-ра запускается асинхронно. Вторая - синхронно по таймеру.
			 
			
					
				Запуск долгой SP
				Добавлено: 21 Апрель 2015, 15:18
				 Ал
				В основной программе вызвать доп.exe - в которой и запускаем для выполнения хранимки, в доп. пишем лог до и после после отработки - по нему в основной или других можно всегда проверить - ещё работает доп.exe или уже всё сделано. Если вызывать в основной например RUN доп.ехе - то по флагу ожидания можно либо вывесить транспарант "работаю.." перед запуском и ждать пока закончит, или ехать дальше, но проверять периодически что там с логом и сообщить когда доп.exe отработает.
			 
			
					
				Запуск долгой SP
				Добавлено: 21 Апрель 2015, 15:18
				 Admin
				В табличку кидаешь @@SPID, @@PROCID и процент выполнения. Параллельно читаешь.
			 
			
					
				Запуск долгой SP
				Добавлено: 21 Апрель 2015, 23:59
				 Aragorn
				Это все хорошо только если в хранимке работать с курсорами - иначе как процент выполнения вычислять?  А курсоры есть зло имхо. Чем вам мой вариант не понравился? там есть кстати метод что-то типа cCommand.MsgWait  и указывается с какой частотой. А асинхронность указывается в опциях _execute...
Вообще хорошо бы знать, чем эта процедура занимается. Там, глядишь, еще б идеи возникли.
			 
			
					
				Запуск долгой SP
				Добавлено: 22 Апрель 2015, 0:18
				 ingasoftplus
				спасибо всем за советы.
Только со СП - засада. В ней просто
и ни каких интервенций тут не получишь - пока не отработает ВСЕ! может быть 1000 записей, а может и 20000...
 
			 
			
					
				Запуск долгой SP
				Добавлено: 22 Апрель 2015, 1:58
				 Aragorn
				Да тут просто море вариантов!
Например, сначала в кларик получить число записей исходной таблицы через Select Count, в хранимку добавить два параметра для указания диапазона выборки и в цикле в кларике вызывать эту хранимку с шагом для изменения диапазона. Отображая все это в прогресс баре...
Или вот еще: табличка с одним полем и одной записью Char(1), там нолик. Или с двумя полями, во втором suser_sname (сорри, мсскул 

), для многопользовательской реализации.  Когда хранимка отрабатывает (асинхронно!!!), пусть пишет туда единичку. А вызвавший код крутит туда-сюда прогресс, опрашивая содержимое записи таблички иногда. Если хранимка работает асинхронно, код провалится дальше в этот цикл с прогресс баром и вывалится по завершению.
Что мне не нравится во втором способе - надо часто (т.е. чаще чем в первом) дергать сервак запросом к табличке состояния.
 
			 
			
					
				Запуск долгой SP
				Добавлено: 22 Апрель 2015, 10:30
				 kreator
				ingasoftplus писал(а):спасибо всем за советы.
Только со СП - засада. В ней просто
Код: Выделить всё
INSERT  from  (select from table)
и ни каких интервенций тут не получишь - пока не отработает ВСЕ! может быть 1000 записей, а может и 20000...
Есть такое понятие, как триггер. В триггер на Insert вставляешь Update какой-нибудь записи какой-нибудь таблицы, а в программе читаешь её. Например, перед Insert вычислить кол-во записей, которое нужно добавить. А в триггере плюсовать добавленные записи. И сравнивать два значения.
Но мне кажется это всё костыли какие-то. Лучше поработать над оптимизацией этого Insert, чтобы запрос происходил быстро, не вызывая у пользователя проблем.