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

Вниз

Загрузка страниц в Потоке с idHTTP   Найти похожие ветки 

 
Pcrepair ©   (2012-12-11 23:03) [0]

Добрый день. Есть код:

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 или устарело. а чем заменить?


 
DVM ©   (2012-12-12 00:27) [1]


>    ThreadLdr.Url:=ListBox1.Items[ListBox1.ItemIndex]; (*передаем
> УРЛ из ЛБ в Поток, все работает*)
>    HtmlCode:=ThreadLdr.Html;  (*получаем результат ТУТ ПУСТО!
> !!*)

вот здесь у тебя ошибка, даже 2 по одной в каждой строке.


 
Медвежонок Пятачок ©   (2012-12-12 05:09) [2]

procedure TLoader.Execute;
begin
 Synchronize(LoadPage);
end;


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


 
Медвежонок Пятачок ©   (2012-12-12 05:21) [3]

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.


 
Pcrepair ©   (2012-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;


а как правильно вернуть полученные данные?

Медвежонок Пятачок
если ты не понял - это демокод, просто наглядный пример

> Задача была такая: загрузить страницу посредством idHTTP
> но с использованием класса TThread.

а ты предлагаешь вообще поток удалить. что называется: здгавствуй ЖНГ!!
//ThreadLdr:=Tloader.Create(True); - это как понимать? тебе нравится AV?


 
brother ©   (2012-12-12 08:01) [5]

Ты не понимаешь как работать с потоками?


 
Медвежонок Пятачок ©   (2012-12-12 08:03) [6]

Все что делает твой поток:

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

больше он ничего не делает.


 
brother ©   (2012-12-12 08:03) [7]

читай это: http://www.delphimaster.ru/articles/panov/
обрати внимание на:
Так как процедура, вызываемая в методе Synchronize выполняется в основном потоке, то на время выполнения Synchronize главная форма будет блокирована для ввода, обновления информации, как это происходит при длительных операциях в основном потоке.
Поэтому этот метод надо вызывать по возможности реже.


 
Медвежонок Пятачок ©   (2012-12-12 08:15) [8]

а ты предлагаешь вообще поток удалить. что называется: здгавствуй ЖНГ!!
//ThreadLdr:=Tloader.Create(True); - это как понимать? тебе нравится AV?


Никакого АВ, дурашка не будет.
Потому что не будет обращения к твоему бесполезному потоку.
Все строки связанные с ним у меня закоментированы.
а idHTTP1 положи на форму, если ты об этом.


 
Германн ©   (2012-12-12 09:56) [9]


> Задача была такая: загрузить страницу посредством idHTTP
> но с использованием класса TThread. Вроде все по теории?
>

Ага. Осталось малое.
Научиться запуздыривать в Synchronize функцию, а не процедуру!
Вот только противный РАД этого не позволяет :(


 
DVM ©   (2012-12-12 10:07) [10]


> 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 10:11) [11]

самое простое - убрать фрионтерминэйт.
хтмл сразу перестанет пропадать.
убить поток явно.
но страницу грузить будет все равно основной.


 
DVM ©   (2012-12-12 10:20) [12]


> Pcrepair ©   (12.12.12 07:52) 

Вообще, конечно, если твоя программа будет работать долго и грузить много-много URL, то стоит подумать над организацией пула потоков, чтоб потоки не создавать/уничтожать каждый раз (это уже не очень хорошо), а брать свободный в данный момент из пула.
Потоки, которые свою задачу выполнили, должны засыпать и просыпаться по событию, которое должно взводиться в тот момент, когда им передали очередное задание.
Ведь я так понимаю, возвращенные HTML страницы подвергаются какому то анализу, этот анализ тоже не надо делать в основном потоке. И вообще GUI - он только для визуализации процесса.


 
Pcrepair ©   (2012-12-12 18:37) [13]


> Медвежонок Пятачок ©   (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 - он только для визуализации процесса.

вот это наверно то что нужно, урл будет ну очень много
а примеры подобных решений кто нибуть знает?


 
Медвежонок Пятачок ©   (2012-12-12 19:34) [14]

....
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 21:11) [15]

Удалено модератором


 
Медвежонок Пятачок ©   (2012-12-12 21:18) [16]

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

я тебе прокомментировал.


 
Pcrepair ©   (2012-12-12 21:22) [17]

Удалено модератором


 
Медвежонок Пятачок ©   (2012-12-12 21:24) [18]

Удалено модератором


 
Медвежонок Пятачок ©   (2012-12-12 21:29) [19]

Удалено модератором


 
Игорь Шевченко ©   (2012-12-12 21:32) [20]

Lamers must die!


 
имя   (2012-12-12 22:36) [21]

Удалено модератором



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

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

Наверх




Память: 0.54 MB
Время: 0.005 c
15-1363546955
О-Сознание
2013-03-17 23:02
2013.08.18
Пароли


6-1268845954
Vigi
2010-03-17 20:12
2013.08.18
Как правильно реализовать ?


15-1363171562
Jeer
2013-03-13 14:46
2013.08.18
Почти парад планет в эти дни -


15-1363638605
Юрий
2013-03-19 00:30
2013.08.18
С днем рождения ! 19 марта 2013 вторник


15-1363768712
Polevi
2013-03-20 12:38
2013.08.18
не могу вспомнить название библиотеки