Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2009.11.29;
Скачать: CL | DM;

Вниз

процедура возвращающая параметр заполняемые в потоке   Найти похожие ветки 

 
antonn ©   (2009-09-20 18:12) [0]

Вот, значит :)
Есть некий класс, с методом
SendPOST(const URL:string; response:string)

делает он то, что отправляет хттп POST-запрос на сервер. Хочу выделить для этого доп.поток, но так, чтобы обходиться функцией с приведенными параметрами и не вводить обработчиков вызываемых при отработке потока (метод уже используется в других классах, переписывать много).
Пока только придумал делать бесконечный цикл в котором ждать отклика потока об успешной операции (ну и добавить sleep(1) да application.ProcessMessages). Есть более нормальное решение? :)


 
Ega23 ©   (2009-09-20 18:54) [1]

Бред какой-то. Зачем тебе доп.поток тогда нужен?
И нафига sleep(1) если ProcessMessages уже вызвал?


 
antonn ©   (2009-09-20 19:10) [2]

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

Sleep(1) "визуально разгружает" проц :)


 
Ega23 ©   (2009-09-20 19:39) [3]


> вызывает метод моего класса, который услужливо должен отдать
> им результат запроса на сервер.

Если у тебя в основном потоке стоит ожидание результата - ты хоть апстену убейся, но доп.поток тебя не спасёт. Никак. Хоть 9000 потоков навешивай.


 
antonn ©   (2009-09-20 19:53) [4]

да ну :)
function THTTPClient.SendPostURL(const URL:string; const Data:tmemorystream):boolean;
var PacingCounter:int64;
begin
 result:=false;
 PacingCounter:=GetTickCount;
 FPostResponsed:=-1;
 THTTPPOSTNode.create(0,ProxyHost,ProxyPort,ProxyUser,ProxyPass,url,data);
 while not(application.terminated) do begin
   if(FPostResponsed>-1) then begin
     result:=true;
     //комплит
     exit;
   end;
   if (GetTickCount-PacingCounter>10000) then begin
 
      break;
   end;
   sleep(1);
   application.ProcessMessages;
 end;
end;

THTTPPOSTNode - класс доп.потока, FPostResponsed - флаг меняемый когда поток закончит работу (после окончания он уведомляет об этом родителя).
Разумеется с таким подходом нельзя подряд быстро вызывать SendPostURL, флаг то один, но мне это не нужно. Форма и контролы на ней живут обычной жизнью, и ничего не напоминает зависания. Просто мне сам способ такой кажется костыльным :)


 
Медвежонок Пятачок ©   (2009-09-20 20:03) [5]

зачем тебе поток и зачем тебе его ожидание, если и без потока и без ожидания все будет точно так же как и с потоком и с ожиданием?


 
antonn ©   (2009-09-20 20:43) [6]


> Медвежонок Пятачок ©   (20.09.09 20:03) [5]
>
> зачем тебе поток и зачем тебе его ожидание, если и без потока
> и без ожидания все будет точно так же как и с потоком и
> с ожиданием?

->

> да ну :)


с потоком форма не "залипает", можно прикрутить человеческую анимацию этого процесса


 
Медвежонок Пятачок ©   (2009-09-20 20:47) [7]

для этих случаев есть TidAntiFreeze


 
antonn ©   (2009-09-20 20:50) [8]

Инди - это такие маленькие офисные игрушки, да?


 
antonn ©   (2009-09-20 21:03) [9]

в общем оторвитесь от нутрей потока и что он там отправляет, хочу более универсальное решение :)

По другому распишу. Допустим есть метод класса:
function TTG.Post(url:string; var st:Tstrings):boolean;
begin
   sleeeep(150000);
   //какое то долговыполняемое действие.
   st.add("ok");
end;


У экземпляров этого класса вызывается этот метод, и он вешает программу. Но я не могу поправить код, который вызывает мой метод, они его запускают и после отработки получают результат в передаваемый TStrings.
Мало того, что на время отработки метода приложение подвисает, так еще и вызов подряд этого метода у нескольких экземпляров класса займет немало времени (относительно многопоточности) и, опять же, подвесит форму приложения.
Отсюда и родился тот костыль из [4], там создается поток которому передаются нужные параметры, он выполняет напряжную работу и после окончания передает результат моему классу. Нужно было решение которое позволит функции "подождать" пока поток все сделает и не дать всему приложению зависнуть в ожидании.


 
Юрий Зотов ©   (2009-09-20 22:14) [10]

> У экземпляров этого класса вызывается этот метод, и он вешает
< программу. Но я не могу поправить код, который вызывает мой метод,

А переопределмить? override.


 
antonn ©   (2009-09-20 22:56) [11]

тоже не могу, это "не моя территория", так же как попросить переделать ответственного :)

мне хочется узнать:

> решение которое позволит функции "подождать" пока поток
> все сделает и не дать всему приложению зависнуть в ожидании.
>

Есть ли такое? т.е. кусок внутри процедуры я выношу в поток только для одной вещи - чтобы оно не вешало основной поток приложения и не мешало выполнению других функций (ну хотя бы отрисовке формы).


 
Медвежонок Пятачок ©   (2009-09-20 23:26) [12]

мне хочется узнать:

> решение которое позволит функции "подождать" пока поток
> все сделает и не дать всему приложению зависнуть в ожидании.
>

для этих случаев есть TidAntiFreeze


 
Achpile ©   (2009-09-20 23:29) [13]

вообще поток создается функцией CreateThread... Туда передаешь процедуру, а возвращается handle твоего нового потока


 
qwer_qwer   (2009-09-20 23:57) [14]


> Есть ли такое? т.е. кусок внутри процедуры я выношу в поток
> только для одной вещи - чтобы оно не вешало основной поток
> приложения и не мешало выполнению других функций (ну хотя
> бы отрисовке формы).


В чём проблема? - Вынеси код с действиями после получения ответа в отдельную процедуру и выполняй после завершения доп. потока.
Ждать вообще ничего не придётся.


 
antonn ©   (2009-09-21 01:06) [15]


> Ждать вообще ничего не придётся.

еще раз... :(

есть какой то код (чужой), работает примерно так:
st:=Tstringlist.Create;
 try
   //что то делает
   FTG.Post("ya.ru",st);
   //еще что то делает
 finally
   st.free;
 end;

вызывается метод экземпляра моего класса(FTG:TTG из [9]), вызвал - передал параметры, получил обратно - попер дальше. Выше (в [9]) примерный код внутри моего метода (он просто напряжный и долгий, для наглядности там стоит sleep()). При его вызове "как сейчас" форма зависнет намертво (специально для Медвежонков-Пяточков скажу, что TidAntiFreeze не помогает, странно, да? :)).
Если я создам TThread и перенесу в него напряжные расчеты и крикну ему "resume!" то вероятно после этого код в "родительском" потоке "пойдет дальше" (где то я уже ловился на этом и создавал тут тему, когда по невнимательности разрушал класс до того, как поток вернет результат ). А мне нужно в основном потоке "подождать" выполнения кода в доппотоке (их может быть несколько) и не повесить форму, и вернуть результат в передаваемом параметре метода (тут - в var st:Tstrings).

Может я не вижу очевидного, не могли бы набросать простой скелет такой конструкции?


 
Германн ©   (2009-09-21 01:45) [16]


> Может я не вижу очевидного

Мне кажется, что не видишь.
При таком чужом коде я не вижу способа перенести хоть что-то в другой поток для избавления основного потока от зависания.
P.S. Единственное нормальное решение тут указано в Юрий Зотов ©   (20.09.09 22:14) [10].


 
Германн ©   (2009-09-21 02:01) [17]


> Если я создам TThread и перенесу в него напряжные расчеты
> и крикну ему "resume!" то вероятно после этого код в "родительском"
> потоке "пойдет дальше" (где то я уже ловился на этом и создавал
> тут тему, когда по невнимательности разрушал класс до того,
>  как поток вернет результат ).

Ну вот тут тот самый случай, имхо. Ты перенесёшь в доппоток "напряжёнку" и выйдешь из твоего метода  FTG.Post. Сразу после этого чужой код "ещё что-то сделает" и уничтожит экземпляр Tstringlist.


 
DVM ©   (2009-09-21 08:25) [18]


> antonn ©   (21.09.09 01:06) [15]

Ты очевидно хочешь странного, по крайней мере это странно выглядит с твоих слов. Чтоб интерфейс не подвисал, ты выносишь долгие вычисления в доп поток, но потом хочешь ждать завершения этого потока, тем самым ожидание завершения потока заморозят тебе интерфейс.

Чтобы не подвисал интерфейс надо:
1) Создать доп поток, запустить там долгие вычисления.
2) В основном потоке создать цикл (!) ожидающий окончания работы доп потока (метод проверки придумай сам) и вызывающий в этом цикле Application.ProcessMessages периодически. Еще лучше перед запуском потока погасить все прочие контролы, а то поток еще раз запустят того гляди.

А вообще это странно - либо синхронная либо асинхронная работа, мешать одно с другим имхо плохо.


 
Медвежонок Пятачок ©   (2009-09-21 09:07) [19]

1) Создать доп поток, запустить там долгие вычисления.
2) В основном потоке создать цикл (!)


вот только не надо этого дибилизма.
если уж применяется поток, то он сам должен сигнализировать о том что завершил работу и результат готов.

либо вообще не трогать потоки, а использовать антифириз.


 
Сергей М. ©   (2009-09-21 09:22) [20]

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;


 
Anatoly Podgoretsky ©   (2009-09-21 11:57) [21]

> Медвежонок Пятачок  (21.09.2009 09:07:19)  [19]

Лучше не использовать антифириз


 
Сергей М. ©   (2009-09-21 12:04) [22]


> Лучше не использовать антифириз


Угу.
В очумелых ручках индейский антифриз превращается в букет граблей.

Да и лучше не использовать индейцев вообще. Без особой на то нужды, разумеется.


 
Медвежонок Пятачок ©   (2009-09-21 12:08) [23]

Лучше не использовать антифириз

Я и не говорил, что лучше.
Он был предложен в связи с тем, что поток ему хочется, а рефакторить код под поток не хочется


 
antonn ©   (2009-09-21 12:13) [24]


> Чтобы не подвисал интерфейс надо:
> 1) Создать доп поток, запустить там долгие вычисления.
> 2) В основном потоке создать цикл (!) ожидающий окончания
> работы доп потока (метод проверки придумай сам) и вызывающий
> в этом цикле Application.ProcessMessages периодически. Еще
> лучше перед запуском потока погасить все прочие контролы,
>  а то поток еще раз запустят того гляди.

это я сделал в [4], мне показалось костылем, вот и создал тему... Оно работает, интерфейс не морозится, на любых "трудноперевариваемых" данных и при нескольких потоках, но кажется костылем :)


 
antonn ©   (2009-09-21 12:13) [25]


> а рефакторить код под поток не хочется

не можется


 
DVM ©   (2009-09-21 21:40) [26]


> Медвежонок Пятачок ©   (21.09.09 09:07) [19]


> вот только не надо этого дибилизма.

Не надо мне тут рассказвать про дибилизм. Это единственный способ добиться в точности того, что он хочет. Антифриз это из другой оперы совсем и применять его надо совсем в другом случае.


 
DVM ©   (2009-09-21 21:44) [27]


> antonn ©   (21.09.09 12:13) [24]


> это я сделал в [4], мне показалось костылем, вот и создал
> тему...

А это и есть костыль. По хорошему так не стоит делать.


 
dima_q   (2009-10-14 11:32) [28]

Если тема еще актуальна, то лучшее решение для твоего вопроса здесь: http://www.delphikingdom.ru/asp/viewitem.asp?catalogid=1355



Страницы: 1 вся ветка

Текущий архив: 2009.11.29;
Скачать: CL | DM;

Наверх




Память: 0.55 MB
Время: 0.013 c
15-1254078510
DillerXX
2009-09-27 23:08
2009.11.29
подскажите как сделать avi из картинки + mp3


15-1254496978
Германн
2009-10-02 19:22
2009.11.29
Название контакта датчика


15-1254244818
tesseract
2009-09-29 21:20
2009.11.29
литература по posix


2-1255072442
novai
2009-10-09 11:14
2009.11.29
Работа с указателями


15-1254455614
RDen
2009-10-02 07:53
2009.11.29
Закрываете обсуждение, дак хоть причину в двух словах указывайте