![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
процедура возвращающая параметр заполняемые в потоке [D6, D7, 2000, XP, 2003]
antonn © (2009-09-20 18:12:00)Вот, значит :)
Есть некий класс, с методом
SendPOST(const URL:string; response:string)
делает он то, что отправляет хттп POST-запрос на сервер. Хочу выделить для этого доп.поток, но так, чтобы обходиться функцией с приведенными параметрами и не вводить обработчиков вызываемых при отработке потока (метод уже используется в других классах, переписывать много).
Пока только придумал делать бесконечный цикл в котором ждать отклика потока об успешной операции (ну и добавить sleep(1) да application.ProcessMessages). Есть более нормальное решение? :)
dima_q (2009-10-14 11:32:00) [1]Если тема еще актуальна, то лучшее решение для твоего вопроса здесь: http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=1355
DVM (2009-09-21 21:44:00) [2]
> antonn © (21.09.09 12:13) [24]
> это я сделал в [4], мне показалось костылем, вот и создал
> тему...
А это и есть костыль. По хорошему так не стоит делать.
DVM (2009-09-21 21:40:00) [3]
> Медвежонок Пятачок © (21.09.09 09:07) [19]
> вот только не надо этого дибилизма.
Не надо мне тут рассказвать про дибилизм. Это единственный способ добиться в точности того, что он хочет. Антифриз это из другой оперы совсем и применять его надо совсем в другом случае.
antonn (2009-09-21 12:13:00) [4]
> а рефакторить код под поток не хочется
не можется
antonn (2009-09-21 12:13:00) [5]
> Чтобы не подвисал интерфейс надо:
> 1) Создать доп поток, запустить там долгие вычисления.
> 2) В основном потоке создать цикл (!) ожидающий окончания
> работы доп потока (метод проверки придумай сам) и вызывающий
> в этом цикле Application.ProcessMessages периодически. Еще
> лучше перед запуском потока погасить все прочие контролы,
> а то поток еще раз запустят того гляди.
это я сделал в [4], мне показалось костылем, вот и создал тему... Оно работает, интерфейс не морозится, на любых "трудноперевариваемых" данных и при нескольких потоках, но кажется костылем :)
Медвежонок Пятачок (2009-09-21 12:08:00) [6]Лучше не использовать антифириз
Я и не говорил, что лучше.
Он был предложен в связи с тем, что поток ему хочется, а рефакторить код под поток не хочется
Сергей М. (2009-09-21 12:04:00) [7]
> Лучше не использовать антифириз
Угу.
В очумелых ручках индейский антифриз превращается в букет граблей.
Да и лучше не использовать индейцев вообще. Без особой на то нужды, разумеется.
Anatoly Podgoretsky (2009-09-21 11:57:00) [8]> Медвежонок Пятачок (21.09.2009 09:07:19) [19]
Лучше не использовать антифириз
Сергей М. (2009-09-21 09:22:00) [9]
TMyThread = class(TThread)
..
FURL: String;
FResponse: TStrings;
..
property Response: TStrings read FResponse;
..
end;
..
procedure TMyThread.Exceute;
begin
..
FResponse := SengRequest(FURL); //make blocking call
..
end;
..
var
hThread: THandle;
Msg: TMsg;
..
MyThread := TMyThread.Create(URL);
try
hThread := MyThread.Handle;
while not Application.Terminated do
case MsgWaitForMultilpeObjects(1, hThread, False, INFINITE, QS_ALLINPUT) of
WAIT_OBJECT_0:
begin
if Assigned(MyThread.FatalException) then
raise MyThread.FatalException;
ShowMessage(MyThread.Response.Text);
break;
end;
WAIT_OBJECT_0 + 1:
begin
PeekMessage(Msg, 0, 0, 0, PM_REMOVE);
Application.ProcessMessage(Msg);
end;
end;
finally
MyThread.Free;
end;
Медвежонок Пятачок (2009-09-21 09:07:00) [10]1) Создать доп поток, запустить там долгие вычисления.
2) В основном потоке создать цикл (!)
вот только не надо этого дибилизма.
если уж применяется поток, то он сам должен сигнализировать о том что завершил работу и результат готов.
либо вообще не трогать потоки, а использовать антифириз.
DVM (2009-09-21 08:25:00) [11]
> antonn © (21.09.09 01:06) [15]
Ты очевидно хочешь странного, по крайней мере это странно выглядит с твоих слов. Чтоб интерфейс не подвисал, ты выносишь долгие вычисления в доп поток, но потом хочешь ждать завершения этого потока, тем самым ожидание завершения потока заморозят тебе интерфейс.
Чтобы не подвисал интерфейс надо:
1) Создать доп поток, запустить там долгие вычисления.
2) В основном потоке создать цикл (!) ожидающий окончания работы доп потока (метод проверки придумай сам) и вызывающий в этом цикле Application.ProcessMessages периодически. Еще лучше перед запуском потока погасить все прочие контролы, а то поток еще раз запустят того гляди.
А вообще это странно - либо синхронная либо асинхронная работа, мешать одно с другим имхо плохо.
Германн (2009-09-21 02:01:00) [12]
> Если я создам TThread и перенесу в него напряжные расчеты
> и крикну ему "resume!" то вероятно после этого код в "родительском"
> потоке "пойдет дальше" (где то я уже ловился на этом и создавал
> тут тему, когда по невнимательности разрушал класс до того,
> как поток вернет результат ).
Ну вот тут тот самый случай, имхо. Ты перенесёшь в доппоток "напряжёнку" и выйдешь из твоего метода FTG.Post. Сразупосле этого чужой код "ещё что-то сделает" и уничтожит экземпляр Tstringlist.
Германн (2009-09-21 01:45:00) [13]
> Может я не вижу очевидного
Мне кажется, что не видишь.
При таком чужом коде я не вижу способа перенести хоть что-то в другой поток для избавления основного потока от зависания.
P.S. Единственное нормальное решение тут указано в Юрий Зотов © (20.09.09 22:14) [10].
antonn (2009-09-21 01:06:00) [14]
> Ждать вообще ничего не придётся.
еще раз... :(
есть какой то код (чужой), работает примерно так:
st:=Tstringlist.Create;
try
//что то делает
FTG.Post('ya.ru',st);
//еще что то делает
finally
st.free;
end;
вызывается метод экземпляра моего класса(FTG:TTG из [9]), вызвал - передал параметры, получил обратно - попер дальше. Выше (в [9]) примерный код внутри моего метода (он просто напряжный и долгий, для наглядности там стоит sleep()). При его вызове "как сейчас" форма зависнет намертво (специально для Медвежонков-Пяточков скажу, что TidAntiFreeze не помогает, странно, да? :)).
Если я создам TThread и перенесу в него напряжные расчеты и крикну ему "resume!" то вероятно после этого код в "родительском" потоке "пойдет дальше" (где то я уже ловился на этом и создавал тут тему, когда по невнимательности разрушал класс до того, как поток вернет результат ). А мне нужно в основном потоке "подождать" выполнения кода в доппотоке (их может быть несколько) и не повесить форму, и вернуть результат в передаваемом параметре метода (тут - в var st:Tstrings).
Может я не вижу очевидного, не могли бы набросать простой скелет такой конструкции?
qwer_qwer (2009-09-20 23:57:00) [15]
> Есть ли такое? т.е. кусок внутри процедуры я выношу в поток
> только для одной вещи - чтобы оно не вешало основной поток
> приложения и не мешало выполнению других функций (ну хотя
> бы отрисовке формы).
В чём проблема? - Вынеси код с действиями после получения ответа в отдельную процедуру и выполняй после завершения доп. потока.
Ждать вообще ничего не придётся.
Achpile (2009-09-20 23:29:00) [16]вообще поток создается функцией CreateThread... Туда передаешь процедуру, а возвращается handle твоего нового потока
Медвежонок Пятачок (2009-09-20 23:26:00) [17]мне хочется узнать:
> решение которое позволит функции "подождать" пока поток
> все сделает и не дать всему приложению зависнуть в ожидании.
>
для этих случаев есть TidAntiFreeze
antonn (2009-09-20 22:56:00) [18]тоже не могу, это "не моя территория", так же как попросить переделать ответственного :)
мне хочется узнать:
> решение которое позволит функции "подождать" пока поток
> все сделает и не дать всему приложению зависнуть в ожидании.
>
Есть ли такое? т.е. кусок внутри процедуры я выношу в поток только для одной вещи - чтобы оно не вешало основной поток приложения и не мешало выполнению других функций (ну хотя бы отрисовке формы).
Юрий Зотов (2009-09-20 22:14:00) [19]> У экземпляров этого класса вызывается этот метод, и он вешает
< программу. Но я не могу поправить код, который вызывает мой метод,
А переопределмить? override.
antonn (2009-09-20 21:03:00) [20]в общем оторвитесь от нутрей потока и что он там отправляет, хочу более универсальное решение :)
По другому распишу. Допустим есть метод класса:
function TTG.Post(url:string; var st:Tstrings):boolean;
begin
sleeeep(150000);
//какое то долговыполняемое действие.
st.add('ok');
end;
У экземпляров этого класса вызывается этот метод, и он вешает программу. Но я не могу поправить код, который вызывает мой метод, они его запускают и после отработки получают результат в передаваемый TStrings.
Мало того, что на время отработки метода приложение подвисает, так еще и вызов подряд этого метода у нескольких экземпляров класса займет немало времени (относительно многопоточности) и, опять же, подвесит форму приложения.
Отсюда и родился тот костыль из [4], там создается поток которому передаются нужные параметры, он выполняет напряжную работу и после окончания передает результат моему классу. Нужно было решение которое позволит функции "подождать" пока поток все сделает и не дать всему приложению зависнуть в ожидании.