![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Загрузка страниц в Потоке с idHTTP
Pcrepair © (2012-12-11 23:03:00)Добрый день. Есть код:
unit Unit1;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm1 = class(TForm)
Memo1: TMemo;
ListBox1: TListBox;
procedure ListBox1DblClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}
uses uThreadLoader;
procedure TForm1.ListBox1DblClick(Sender: TObject);
var ThreadLdr: TLoader; HtmlCode:string;
begin
ThreadLdr:=Tloader.Create(True); (*создаем поток*)
ThreadLdr.Priority:=tpNormal; (*задать приортет нормальный*)
ThreadLdr.FreeOnTerminate:=True; (*самовыгрузка в конце потока*)
ThreadLdr.Resume; (*запускаю поток - что то устаревшее заменить?*)
ThreadLdr.Url:=ListBox1.Items[ListBox1.ItemIndex]; (*передаем УРЛ из ЛБ в Поток, все работает*)
HtmlCode:=ThreadLdr.Html; (*получаем результат ТУТ ПУСТО!!!*)
Memo1.Lines.Add(HtmlCode); (*выводим результат в МЕМО*)
end;
end.
и дополнительный модуль
unit uThreadLoader;
interface
uses
System.Classes, idHTTP, SysUtils, Dialogs;
type
TLoader = class(TThread)
private
{ Private declarations }
protected
procedure Execute; override;
procedure LoadPage;
public
Url, Html:string;
end;
implementation
procedure Tloader.LoadPage;
var
Ldr:TidHTTP;
begin
Ldr:=TidHTTP.Create(nil);
Html:=Ldr.Get(Url);
ShowMessage(Html); (*тут страница есть*)
FreeAndNil(Ldr);
end;
procedure TLoader.Execute;
begin
Synchronize(LoadPage);
end;
end.
Задача была такая: загрузить страницу посредством idHTTP но с использованием класса TThread. Вроде все по теории?
Вопросы:
- почему не передается код страницы в HtmlCode:=ThreadLdr.Html;???? УРЛ через переменную доходит до idHTTP, а обратно нет
- РАД говорит что [dcc32 Warning] Unit1.pas(44): W1000 Symbol 'Resume' is deprecated или устарело. а чем заменить?
(2012-12-12 22:36:00) [1]Удалено модератором
Игорь Шевченко (2012-12-12 21:32:00) [2]Lamers must die!
Медвежонок Пятачок (2012-12-12 21:29:00) [3]Удалено модератором
Медвежонок Пятачок (2012-12-12 21:24:00) [4]Удалено модератором
Pcrepair (2012-12-12 21:22:00) [5]Удалено модератором
Медвежонок Пятачок (2012-12-12 21:18:00) [6]ты просил меня прокомментировать почему лоадпейдж выполнялся в главном потоке?
я тебе прокомментировал.
Pcrepair (2012-12-12 21:11:00) [7]Удалено модератором
Медвежонок Пятачок (2012-12-12 19:34:00) [8]....
ThreadLdr:=Tloader.Create(True); (*создаем поток*)
LogToFile('Привет, я процедура главного потока. Вот мой ThreadID: ' + IntToStr(GetCurrentThreadID));
ThreadLdr.Priority:=tpNormal; (*задать приортет нормальный*)
....
procedure Tloader.LoadPage;
var
Ldr:TidHTTP;
begin
LogToFile('Привет, а я типа тоже метод вторичного потока. Но выполняюсь я вот здесь: ' + IntToStr(GetCurrentThreadID));
Ldr:=TidHTTP.Create(nil);
Html:=Ldr.Get(Url);
ShowMessage(Html); (*тут страница есть*)
FreeAndNil(Ldr);
end;
procedure TLoader.Execute;
begin
LogToFile('Привет, я метод Execute вторичного потока. Вот мой ThreadID ' + IntToStr(GetCurrentThreadID));
Synchronize(LoadPage);
end;
... Где LogToFile - процедура записи в текстовый файл
Pcrepair (2012-12-12 18:37:00) [9]
> Медвежонок Пятачок © (12.12.12 08:03) [6]
> Все что делает твой поток:
>
> просит главный поток, что бы тот закачал этот урл
> ждет когда главный закачает.
почему главный поток? главный поток это ведь форма. на форме обработчик который вызывает из доп. модуля поток, передает ему УРЛ и получает назад код страницы. на форме нет никаких компонентов, которые могут закачивать страницу. если не сложно, дай свой комментарий
++++++++++++++++++++++++++++++++++++++++++++
> brother © (12.12.12 08:03) [7]
> Так как процедура, вызываемая в методе Synchronize выполняется
> в основном потоке, то на время выполнения Synchronize главная
> форма будет блокирована для ввода, обновления информации,
> как это происходит при длительных операциях в основном
> потоке.
> Поэтому этот метод надо вызывать по возможности реже.
ну да, да сейчас доп. модуль такой:
implementation
uses Unit1;
procedure TLoader.ShowPage;
begin
Form1.Memo1.Lines.Add(Html);
end;
procedure Tloader.LoadPage;
var
Ldr:TidHTTP;
begin
Ldr:=TidHTTP.Create(nil);
Html:=Ldr.Get(Url);
FreeAndNil(Ldr);
end;
procedure TLoader.Execute;
begin
LoadPage;
Synchronize(ShowPage);
end;
И в общем то работает, вот только uses Unit1; мне не нравится, так вроде не надо? что касается Synchronize, этот код чиста для понимания работы потока
++++++++++++++++++++++++++++++++++++++++++++++++
> DVM © (12.12.12 10:20) [12]
> Вообще, конечно, если твоя программа будет работать долго
> и грузить много-много URL, то стоит подумать над организацией
> пула потоков, чтоб потоки не создавать/уничтожать каждый
> раз (это уже не очень хорошо), а брать свободный в данный
> момент из пула.
> Потоки, которые свою задачу выполнили, должны засыпать и
> просыпаться по событию, которое должно взводиться в тот
> момент, когда им передали очередное задание.
> Ведь я так понимаю, возвращенные HTML страницы подвергаются
> какому то анализу, этот анализ тоже не надо делать в основном
> потоке. И вообще GUI - он только для визуализации процесса.
вот это наверно то что нужно, урл будет ну очень много
а примеры подобных решений кто нибуть знает?
DVM (2012-12-12 10:20:00) [10]
> Pcrepair © (12.12.12 07:52)
Вообще, конечно, если твоя программа будет работать долго и грузить много-много URL, то стоит подумать над организацией пула потоков, чтоб потоки не создавать/уничтожать каждый раз (это уже не очень хорошо), а брать свободный в данный момент из пула.
Потоки, которые свою задачу выполнили, должны засыпать и просыпаться по событию, которое должно взводиться в тот момент, когда им передали очередное задание.
Ведь я так понимаю, возвращенные HTML страницы подвергаются какому то анализу, этот анализ тоже не надо делать в основном потоке. И вообще GUI - он только для визуализации процесса.
Медвежонок Пятачок (2012-12-12 10:11:00) [11]самое простое - убрать фрионтерминэйт.
хтмл сразу перестанет пропадать.
убить поток явно.
но страницу грузить будет все равно основной.
DVM (2012-12-12 10:07:00) [12]
> Pcrepair © (12.12.12 07:52) [4]
> DVM
>
> > вот здесь у тебя ошибка, даже 2 по одной в каждой строке.
>
>
> а если канкретно?
> ну ясно что правильно будет
>
> ThreadLdr:=Tloader.Create(True); (*создаем поток*)
> ThreadLdr.Priority:=tpNormal; (*задать приортет нормальный*)
> ThreadLdr.FreeOnTerminate:=True; (*самовыгрузка в конце
> потока*)
> ThreadLdr.Url:=ListBox1.Items[ListBox1.ItemIndex];
> ThreadLdr.Resume;
>
> а как правильно вернуть полученные данные?
Да много есть способов. От Synchronize(только правильно оформленного) до сообщений. Есть и другие способы. Имхо передачу результата из вторичного потока в поток, где крутится GUI лучше всего делать с помощью сообщений (SendMessage), т.к. это самый естественный для GUI метод.
А чтобы не надо было использовать Resume, сделай конструктор с параметром и поле внутри класса потока в которое помещай значение, переданное в конструктор, а далее это же значение используй в Execute потока.
Германн (2012-12-12 09:56:00) [13]
> Задача была такая: загрузить страницу посредством idHTTP
> но с использованием класса TThread. Вроде все по теории?
>
Ага. Осталось малое.
Научиться запуздыривать в Synchronize функцию, а не процедуру!
Вот только противный РАД этого не позволяет :(
Медвежонок Пятачок (2012-12-12 08:15:00) [14]а ты предлагаешь вообще поток удалить. что называется: здгавствуй ЖНГ!!
//ThreadLdr:=Tloader.Create(True); - это как понимать? тебе нравится AV?
Никакого АВ, дурашка не будет.
Потому что не будет обращения к твоему бесполезному потоку.
Все строки связанные с ним у меня закоментированы.
а idHTTP1 положи на форму, если ты об этом.
brother (2012-12-12 08:03:00) [15]читай это: http://www.delphimaster.ru/articles/panov/
обрати внимание на:
Так как процедура, вызываемая в методе Synchronize выполняется в основном потоке, то на время выполнения Synchronize главная форма будет блокирована для ввода, обновления информации, как это происходит при длительных операциях в основном потоке.
Поэтому этот метод надо вызывать по возможности реже.
Медвежонок Пятачок (2012-12-12 08:03:00) [16]Все что делает твой поток:
рождается.
получает урл.
просит главный поток, что бы тот закачал этот урл
ждет когда главный закачает.
дождавшись, умирает.
больше он ничего не делает.
brother (2012-12-12 08:01:00) [17]Ты не понимаешь как работать с потоками?
Pcrepair (2012-12-12 07:52:00) [18]DVM
> вот здесь у тебя ошибка, даже 2 по одной в каждой строке.
а если канкретно?
ну ясно что правильно будет
ThreadLdr:=Tloader.Create(True); (*создаем поток*)
ThreadLdr.Priority:=tpNormal; (*задать приортет нормальный*)
ThreadLdr.FreeOnTerminate:=True; (*самовыгрузка в конце потока*)
ThreadLdr.Url:=ListBox1.Items[ListBox1.ItemIndex];
ThreadLdr.Resume;
а как правильно вернуть полученные данные?
Медвежонок Пятачок
если ты не понял - это демокод, просто наглядный пример
> Задача была такая: загрузить страницу посредством idHTTP
> но с использованием класса TThread.
а ты предлагаешь вообще поток удалить. что называется: здгавствуй ЖНГ!!
//ThreadLdr:=Tloader.Create(True); - это как понимать? тебе нравится AV?
Медвежонок Пятачок (2012-12-12 05:21:00) [19]HtmlCode:=ThreadLdr.Html; (*получаем результат ТУТ ПУСТО!!!*)
Потому что там уже все умерло.
И ты только чудом не получил AV. А чудо это обусловлено случайным и хаотичным набором инструкций на языке паскаль.
procedure TForm1.ListBox1DblClick(Sender: TObject);
var ThreadLdr: TLoader; HtmlCode:string;
begin
ThreadLdr:=Tloader.Create(True); (*создаем поток*)
ThreadLdr.Priority:=tpNormal; (*задать приортет нормальный*)
ThreadLdr.FreeOnTerminate:=True; (*самовыгрузка в конце потока*)
ThreadLdr.Resume; (*запускаю поток - что то устаревшее заменить?*)
ThreadLdr.Url:=ListBox1.Items[ListBox1.ItemIndex]; (*передаем УРЛ из ЛБ в Поток, все работает*)
HtmlCode:=ThreadLdr.Html; (*получаем результат ТУТ ПУСТО!!!*)
Memo1.Lines.Add(HtmlCode); (*выводим результат в МЕМО*)
end;
end.
Абсолютно эквивалентный твоему код, но только html никуда не пропадает:
/*гет, как и у тебя канает в основном потоке */
procedure TForm1.ListBox1DblClick(Sender: TObject);
var ThreadLdr: TLoader; HtmlCode:string;
begin
//ThreadLdr:=Tloader.Create(True); (*создаем поток*)
//ThreadLdr.Priority:=tpNormal; (*задать приортет нормальный*)
//ThreadLdr.FreeOnTerminate:=True; (*самовыгрузка в конце потока*)
//ThreadLdr.Resume; (*запускаю поток - что то устаревшее заменить?*)
//ThreadLdr.Url:=ListBox1.Items[ListBox1.ItemIndex]; (*передаем УРЛ из ЛБ в
Поток, все работает*)
//HtmlCode:=ThreadLdr.Html; (*получаем результат ТУТ ПУСТО!!!*)
HtmlCode := idTHHP1.Get(ListBox1.Items[ListBox1.ItemIndex]);
Memo1.Lines.Add(HtmlCode); (*выводим результат в МЕМО*)
end;
end.
Медвежонок Пятачок (2012-12-12 05:09:00) [20]procedure TLoader.Execute;
begin
Synchronize(LoadPage);
end;
Можешь сразу выбросить этот поток.
Весь полезный код у него выполняется в основном потоке.