Просмотр полной версии : потоки и indy [delphi]
допустим есть код:
procedure tnew.getln;
var
t:tstringlist;
i:integer;
begin
for i:=0 to form1.memo1.lines.count-1 do
begin
t:=stringlist.create;
t.text:=form1.idhttp1.get(form1.memo1.lines[i]);
form1.memo2.lines.add(t.text);
end;
end;
как сделать, чтобы, скажем, потоков 20 паралельно его выполняли?
пытался примерно вот так:
tnew = class(tthread)
private
procedure getln;
protected
procedure execute; override;
end;
var
form1: tform1;
new1, new2: tnew;
i:integer;
procedure tform1.button1click(sender: tobject);
begin
new1 := tnew.create(true);
new1.freeonterminate := true;
new1.s := '1 thread';
new1.priority := tpnormal;
new2 := tnew.create(true);
new2.freeonterminate := true;
new2.s := '2 thread';
new2.priority := tpnormal;
new1.resume;
new2.resume;
end;
procedure tnew.getln;
var
t:tstringlist;
i:integer;
begin
for i:=0 to form1.memo1.lines.count-1 do
begin
t:=stringlist.create;
t.text:=form1.idhttp1.get(form1.memo1.lines[i]);
form1.memo2.lines.add(t.text);
end;
end;
procedure tnew.execute;
begin
getln;
end;
но idhttp1 вылетает с ошибкой или виснет (непомню точно, влом делфи включать) :(
краем уха слышал про idthreadcomponent, но адекватных примеров его использования я не нашел..
помогите!!!!11
Создавай все компоненты в Execute перед выполнением работы а не в процедурах.
И уничтожай потом в Destroy или где там у тебя завершение.
И делай синхронизацию потоков с формой.
Ты можешь в литровую банку сразу 5 рук засунуть?
З.Ы. И что у тебя за бред с созданием TStringList?
Он у тебя создаётся по сто раз и ни разу не уничтожается!
M_script_
23.04.2010, 14:39
1) Synchronize
2) объект TIdHTTP сделай локальным для потока
Ты можешь в литровую банку сразу 5 рук засунуть?
Если руки кривые, обычно так и делают =)
Создавай все компоненты в Execute перед выполнением работы а не в процедурах.
И уничтожай потом в Destroy или где там у тебя завершение.
З.Ы. И что у тебя за бред с созданием TStringList?
Он у тебя создаётся по сто раз и ни разу не уничтожается!
спасибо, учту.
ды это примерный код, я его тут и придумал (: главное - айдихттп
2) объект TIdHTTP сделай локальным для потока
2) пример можно? :)
2) пример можно? :)
tnew = class(tthread)
private
idHTTP:TIdHTTP;
procedure getln;
protected
procedure execute; override;
end;
cheater_man
23.04.2010, 15:10
один из простых вариантов юзать MPI :)
блин, пример как создавать :)
в tform1.button1click добавить это?
new1.idHTTP=idhttp.create; (или как там правильно создавать?)
new2.idHTTP=idhttp.create;
newN.idHTTP=idhttp.create;
один из простых вариантов юзать MPI :)
"Существуют реализации для языков Фортран 77/90, Си и Си++." :mad:
GhostOnline
23.04.2010, 15:32
IdHttp надо создавать в конструкторе класса потока..и уничтожать в деструкторе (хотя так и не обязательно, у меня например idhttp и потоки существуют независимо друг от друга, у меня что-то вроде многопоточной очереди)
ТС я тебе советую сначала почитать про классы, научится их писать самому, иначе тебе придется ой как трудно в создании мультитредных сетевых аппликаций
С сокетами легче синхронизировать ;)
GhostOnline
23.04.2010, 19:45
С сокетами легче синхронизировать ;)
За базар ответишь? :D Разница-то какая?
Sunstrider
23.04.2010, 20:13
IDhttp легче в изучение
M_script_
23.04.2010, 20:50
Возможных способов синхронизации потоков не так много и ни в одном из них нет особых сложностей.
Разница-то какая?
Можно даже ничего не синхронизировать.А если надо упорядочить доступ к каким то общим данным то крит.секций будет вполне достаточно.
IDhttp легче в изучение
за то rfc знать не будешь :D
GhostOnline
23.04.2010, 21:04
Можно даже ничего не синхронизировать.А если надо упорядочить доступ к каким то общим данным то крит.секций будет вполне достаточно.
за то rfc знать не будешь :D
А крит секции это не синхронизация?
Низачод, сморозил чушь, а теперь чтобы оправдаться вообще загнался
Читать научись.Потом внимательно ещё раз прочти.Юный фанатик делфей.
Что-то мне сдается что юный фанатик дельфей старше тебя
А крит секции это не синхронизация?
Низачод, сморозил чушь, а теперь чтобы оправдаться вообще загнался
Читать научись.Потом внимательно ещё раз прочти.Юный фанатик делфей.
Создавай все компоненты в Execute перед выполнением работы а не в процедурах.
И уничтожай потом в Destroy или где там у тебя завершение.
создаю
tnew = class(tthread)
private
http:TIdHTTP;
cook:tidcookiemanager;
protected
procedure execute; override;end;
procedure tnew.execute;
begin
http:=form1.idhttp1.Create;
http.HandleRedirects:=true;
cook:=form1.idcookiemanager1.Create(http);
http.CookieManager:=cook;
<..>
end;
первый поток грузится, после выдаёт "a component named idcookiemanager1 already exist"
wft? что я делаю не так?
GhostOnline
24.04.2010, 00:48
cook := TIdCookieManager.Create(nil);
И мля, нах не надо его вообще создавать то
просто http.AllowCookies := True; и все
wft? что я делаю не так?
Ты все делаешь не так
form1.idcookiemanager1.Create(http);
что это за конструкотр такой? ты пытаешься создать объект другим компонентом?
Ты все делаешь не так
form1.idcookiemanager1.Create(http);
что это за конструкотр такой? ты пытаешься создать объект другим компонентом?
не ругайся ((:
хз, с какого-то примера скопипастил. ща папрбую как ты сказал.
1n0y, нельзя в потоке просто так использовать компоненты с формы.
Создавай компоненты конкретно в самом потоке!
Вот что-то тип такого:
TMyThread = class(TThread)
private
FCS: RTL_CRITICAL_SECTION;
FH TidHTTP;
FS: TIdIOHandlerStack;
CM: TIdCookieManager;
...
protected
procedure Execute; override;
...
public
constructor Create;
destructor Destroy; override;
....
....
procedure TMyThread.Execute;
var text:string;
begin
{}
FH := TidHTTP.Create;
FS := TIdIOHandlerStack.Create;
CM := TidCookieManager.Create;
{--//--}
FH.IOHandler := FS;
FH.HandleRedirects := true;
FH.CookieManager := CM;
FH.AllowCookies := true;
...
text := FH.Get('');
...
end;
constructor TMyThread.Create;
begin
inherited Create(True);
...
FreeOnTerminate := False;
InitializeCriticalSection(FCS);
Resume;
end;
destructor TMyThread.Destroy;
begin
FreeAndNil(FH);
FreeAndNil(FS);
FreeAndNil(CM);
DeleteCriticalSection(FCS);
end;
уураа! всё работает :)
спасибаспасиба! :-*
ребят, это снова я :rolleyes:
вот функция авторизации, слизана у пухового.
собстно, в чем проблема: в таком виде куки не сохраняются и не передаются, изменить, скажем http.Response.ContentType внутри функции я тоже не могу :(
причем, если переменные и функции не делать локальными для потока (ну, тоесть какбэ один поток паралельный главному юзать) - всё отлично работает.
что я снова сделал не так?
tgo = class(TThread)
private
http:TIdHTTP;
IdCookieManager1:tidcookiemanager;
compressor : tidCompressorZLib;
name, pass,s,s2:string;
post:tstringlist;
function test_log_vk (name, pass : string) : string;
protected
procedure Execute; override;
end;
function tgo.test_log_vk (name, pass : string) : string;
begin
http:=tidhttp.Create;
http.AllowCookies := True;
http.HandleRedirects:=false;
IdCookieManager1 := Tidcookiemanager.Create;
http.CookieManager:=IdCookieManager1;
compressor := tIdCompressorZLib.Create;
http.Compressor := compressor;
http.Request.AcceptEncoding := 'gzip,deflate';
http.Request.UserAgent := 'Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)';
http.ReadTimeout := 10000;
post:=tstringlist.create;
try
http.get ('http://vk.com');
except end;
post.add ('op=a_login_attempt');
try
c:=http.post ('http://vk.com/login.php', post);
except end;
if ansipos('captcha_sid',c) <>0 then
begin
form1.Memo3.Lines.Add('капча!');
if form1.CheckBox10.Checked=true then
synchronize(get_capt_r)
else
begin
synchronize(get_capt_auto);
end;
form1.Memo3.Lines.Add('обезьяны разгадали капчу: '+cap);
post.add ('captcha_sid='+sid);
post.add ('captcha_key='+cap);
try
http.post ('http://vk.com/login.php', post);
except end;
end;
post.Clear;
post.add ('email=' + name);
post.add ('pass=' + pass);
post.add ('expire=');
post.add ('vk=1');
try
s := http.post ('http://login.vk.com/?act=login', post);
except end;
post.Clear;
s2:=copy(s, pos('value=''',s)+7, 56);
post.Add ('op=slogin');
post.Add ('redirect=1');
post.Add ('expire=0');
post.Add ('to=');
form1.Label2.caption:=s2;
post.Add ('s=' + s2);
try
http.post ('http://vk.com/login.php', post);
http.get (http.Response.Location);
except end;
if length(http.Response.Location) = 0 Then
begin
result:='ok';
end
else
begin
result:='no_ok';
end;
end;
Sunstrider
24.04.2010, 23:49
Это код чекера ?
GhostOnline
25.04.2010, 00:20
изменить, скажем http.Response.ContentType внутри функции я тоже не могу
Это свойство только для чтения, его нет смысла изменять.
А с куками что-то непонятно, но скорее всего ты намутил с куки менеджером, например создал не тот который нужно. Покажи как ты вызываешь эту фанкшен свою
Это свойство только для чтения, его нет смысла изменять.
дело в том, что если я отправляю капчу на антигейт - оно меняется с application/x-www-form-urlencoded на multipart/form-data и контакт принимать запрос нехочет :(
А с куками что-то непонятно, но скорее всего ты намутил с куки менеджером, например создал не тот который нужно. Покажи как ты вызываешь эту фанкшен свою
ыы, ну как положено - test_log_vk(name,pass);
ставил бряки на кукименеджер.pas - вроде работает.. нечего не понимаю ;(
Это код чекера ?
это код авторизации. прикрутить можешь к чему угодно :)
GhostOnline
25.04.2010, 16:24
дело в том, что если я отправляю капчу на антигейт - оно меняется с application/x-www-form-urlencoded на multipart/form-data и контакт принимать запрос нехочет
Неправильно. IdHttp.Request.xxxxxx - запрос, IdHttp.Response.xxxxxxxx - ответ
А ты хочешь контент-тайп у ответа изменить, это бессмыссленнно, тут дело в другом.
Для антикапчи можно создать другой экземпляр IDHttp.
А вообще доступ к контент-тайпу запроса можно получить так:
Http.Request.ContentType, но не Http.Response.ContentType как было у тебя
ыы, ну как положено - test_log_vk(name,pass);
Нет, меня интересовал весь код функции в которой ты это делаешь
Неправильно. IdHttp.Request.xxxxxx - запрос, IdHttp.Response.xxxxxxxx - ответ
А ты хочешь контент-тайп у ответа изменить, это бессмыссленнно, тут дело в другом.
Для антикапчи можно создать другой экземпляр IDHttp.
А вообще доступ к контент-тайпу запроса можно получить так:
Http.Request.ContentType, но не Http.Response.ContentType как было у тебя
аа, вот в чем дело :) приму к сведению, спасибо
делаю я это в процедуре tgo.execute;
беру акк, выполняю функцию test_log_vk, и если ответ ок - продолжаю работу с акком. если ответ no_ok - беру другой акк
впринцыпе вопрос с куками решен добавлением HTTP.Request.CustomHeaders.Add('Cookie: remixsid=' + sid), но всёже интересно, почему неработает кукименеджер :(
M_script_
25.04.2010, 17:27
но всёже интересно, почему неработает кукименеджер :(
Может обновить инди?
Может обновить инди?
обновлял вчера. вроде последние индейцы стояли - 10.
и с одним потоком всё работает, вот вчомдело..
GhostOnline
25.04.2010, 19:25
залей куда нибудь свой код, и модуль с формой тоже!
Flame of Soul
25.04.2010, 19:44
procedure tnew.getln;
var
i,t:integer;
begin
t:=form1.memo1.lines.count-1;
for i:=0 to t do
form1.memo2.lines.add(form1.idhttp1.get(form1.memo 1.lines[i]));
end;
так компактнее и побыстрее, хотя по факту маловажно.
AlexTheC0d3r
25.04.2010, 20:12
procedure tnew.getln;
var
i,t:integer;
begin
t:=form1.memo1.lines.count-1;
for i:=0 to t do
form1.memo2.lines.add(form1.idhttp1.get(form1.memo 1.lines[i]));
end;
так компактнее и побыстрее, хотя по факту маловажно.
чем объясняется ввод новой переменной t?
Flame of Soul
25.04.2010, 21:55
чем объясняется ввод новой переменной t?
Delphi не производит разворачивания циклов, как и вынесение инвариантного кода за пределы цикла. То есть в компиляторе нет как такового оптимизатора, вот я и посчтитала что более рационально будет именно так, потому что метод:
for i:=0 to memo1.lines.count – 1 do
будет вызываться в каждой итерации, то есть каждый раз будет подсчитывать количество элементов, а если у нас там элементов несколько тысяч, допустим 2000 строк, собственно не так уж и много, как и посчитать количество их элементов, но так как тип используемый там идет как string а не char и заблогонамеренно неизвестна длина строк, пересчет происходить будет в каждой итерации. Даже если взять что memo1.lines.count было бы постоянным и пересчета не производилось, то в условии у нас стоит математическое выражение memo1.lines.count -1
ну соответственно чтобы не заставлять вести лишние подсчеты и желательно вынести количество элементов в отдельную переменную, если конечно оно у нас постоянно и не меняется в теле цикла на произвольное, допустим код вида:
var i:integer;
begin
for i:=0 to Memo1.Lines.Count-1 do
if (i mod 2 = 0) then begin memo1.Lines.Add('a') end;
end;
во первых доказывает нам что VCL вызывает подсчет в каждой итерации, а во вторых указывает на то что количество элементов в теле цикла при его воздействии на Memo меняется и учитывается, что тоже иногда необходимо. (i mod 2 = 0) использовано только чтобы избежать зацикливания.
Ну и банально даже то что при инкрементации переменной цикла i на более высокое значение компилятор не использует Флаг нуля (ZF) а просто сравнивает значение с 0. Семантически это не верно, но я не вижу в этом особого греха.
AlexTheC0d3r
25.04.2010, 22:06
То, использовать второй пример в цикле for не имеет смысла это понятно, но вот насчет введения новой переменной для хранения неизменяемого математического выражения спорно...
Кстати у компилятора delphi достаточно хороший встроенный оптимизатор
Flame of Soul
25.04.2010, 22:26
Прошу прощения у модераторов за отход от основной темы.
но вот насчет введения новой переменной для хранения неизменяемого математического выражения спорно...
ну во первых оно изменяемо, тут я с вами не согласна, можно рассмотреть ситуации когда количество строк велико и у нас автоперенос по ширене строк, тогда при изменении размеров формы количество строк изменится и цикл закончится в тот момент когда первый раз условие будет нарушено, однако при выносе в переменную - этот фактор не повлияет и количество строк уже не будет совпадать с тем что в переменно, что собственно и может вызвать сбой в программе.
Во вторых, программа не застрахована от посылке сообщений из вне, так как Memo тоже имеет handle что означает что количество строк в ней может измениться если у нас есть пересылка данных с другого потока во время выполнения цикла, а если данных много то и цикл выполняется дискретно,соответственно - порциями которыми выделяет ОС под процесс, ну и что я Вам рассказываю, вы ведь я думаю тоже хороший программист и Сами понимаете это, то есть фактор из вне у нас не повлияет на структуру если count будет считаться в каждой итерации.
Однако если вынести за переменную то мы можем схлопотать 2 эксепшена на основании чего можно заключить то что есть возможность внедрения эксплойта в систему, однако для посылке сообщения у нас естественно должны быть соответствующие права. Не могу так сказать на вскидку насколько серьезная это погрешность но факт того что она есть радует.
Ну и IDA Pro Free совершенно бесплатна как и Оленька, так что отладчик и проверяйте))). А по поводу того что в дельфинчике довольна хороший оптимизатор, не спорю так и есть, но люблю я эту IDE и компилятор не за это)
ну во первых оно изменяемо
нет, у меня по условию в мемо во время проверки нечего не дописывается\удаляется. но за внимание - спасибо :)
vBulletin® v3.8.14, Copyright ©2000-2026, vBulletin Solutions, Inc. Перевод: zCarot