Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Загрузка страниц в Потоке с idHTTP


Страницы:   1 2

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;


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


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо