Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2013.09.15;
Скачать: [xml.tar.bz2];

Вниз

Проблемы с потоками при закачке страниц   Найти похожие ветки 

 
Pcrepair ©   (2012-12-27 11:20) [0]

Добрый день.
Есть функция вида function LoadPage(const Url:string):string; для закачки страниц на базе idHHP.Get, которая обеспечивает:
- закачку страниц с фреймами
- закачку страниц по HTTPs
- смену Request.UserAgent (доп. функция) по Random из списка агентов
- подавление исключений в коде idHHP.Get с записью в лог причин
- вывод сообщений о утечке памяти при закрытии Арр
Сама по себе функция работает нормально, загружает все страницы и без утечки памяти.

Есть код запуска этой функции в многопоточном режиме:

unit Main;
....
implementation
{$R *.dfm}
uses uLoadPage,uGlobalVar;

(*нажимает эту кнопку и понеслось*)
procedure TMainForm.Btn_StartLoadURLsClick(Sender: TObject);
var
UrlList:TStringList; (*эквивалент передаваемого массива строк из ПМ*)
i:integer;
Url:string; (*строка = УРЛ из массива*)
begin
  UrlList:=TStringList.Create;
  UrlList.Text:=Mm_InsSMUrls.Text; (*ввод массива строк УРЛ*)
    (*----ЦИКЛ мульти закачки страниц по числу УРЛ в Mm_InsSMUrls---*)
    for i := 0 to UrlList.Count-1 do
      begin
         Url:=UrlList[i]; (*передача УРЛ*)
         Loader(Url); (*вызов процедуры запуска потока закачки страницы*)
         Sleep(10);  (*страховка от перегрева процессора а также от толпы потоков, которые мешают друг другу?*)
      end;
  FreeAndNil(UrlList);
end;


unit uLoadPage;
interface
uses SysUtils, uThreadLoader, Classes;
Procedure Loader(Url:string);
implementation
Procedure Loader(Url:string);
var ThreadLdr: TLoader;
begin
   ThreadLdr:=Tloader.Create(True);
   ThreadLdr.Priority:=tpNormal;  
   ThreadLdr.FreeOnTerminate:=True;
   ThreadLdr.Url:=Url;
   ThreadLdr.Start;
 end;
end.


unit uThreadLoader;
interface
uses
 System.Classes, idHTTP, SysUtils, Dialogs;
type
 TLoader = class(TThread)
 private
    FUrl:string;
    FHtml:string;
   { Private declarations }
 protected
   procedure Execute; override;
   procedure CallStore;
   function LoadHtmlCode(const Url:string):string;
 public
   property Url: string read FUrl write FUrl;  (*свойство класа, доступное для всей программы*)
   property Html: string read FHtml write FHtml;
 end;

implementation
uses uPageLoader, uLoadPage, uGlobalVar;

function TLoader.LoadHtmlCode(const Url:string):string;
begin
 Result:=LoadPage(Url); (*вызываем функцию загрузки страницы из uPageLoader*)
end;

procedure TLoader.CallStore;
begin
  gStore.Add(Html); (*ввод новой строки в ГлобПерем*)
end;

procedure TLoader.Execute;
begin
  Html:=LoadHtmlCode(Url);  (*загрузка страницы в Поле Класса(свойство)*)
   CS.Enter;  (*вход в КС*)
      CallStore; (*передаем результат в ГП*)
   Cs.Leave;  (*выход из КС*)
end;

end.


unit uPageLoader;
interface
uses Classes, SysUtils, idHTTP, StrUtils, IdSSL, IdSSLOpenSSL;
   function LoadPage(const Url:string):string;  (*Основная функция Юнита*)
   procedure ErrorLog(Url:string);
   function LoadHtmlPage(const PageUrl:string):string;
   function DelJS(const Code:string):string;
   function RestoreFrame(const Code:string):string;
   function RestoreFullUrl(const Code:string; const RootUrl:string):string;
   function GetRandomUserAgent: string;
   var
   Loader:TidHTTP;
   SSL:TIdSSLIOHandlerSocketOpenSSL;

implementation
тут много чего, но все работает, смотри в начало
end.


unit uGlobalVar;
interface
uses Classes, SysUtils, SyncObjs;
var
gStore: TStringList=nil; (*ГП для хранения закачанных страниц*)
CS:TCriticalSection; (*используем КС для передачи результата в основной поток*)
implementation

initialization
  gStore:=TStringList.Create;
  gStore.Duplicates:=dupAccept;
  gStore.Sorted:=False;
  Cs:=TCriticalSection.Create;
finalization
 FreeAndNil(gStore);
 FreeAndNil(CS);
end.


Результат:
В режиме отладки видно что возникает множество самых различных ошибок:
- First chance exception at $00407466. Exception class $C0000005 with message "access violation at 0x00407466: read of address 0x000000a4". Process Loader_VER06.exe (2012)
- First chance exception at $7C812AFB. Exception class EIdHTTPProtocolException with message "Set-Cookie: dle_password=deleted; expires=Tue, 27-Dec-2011 20:37:50 GMT; path=/; domain=.freeseller.ru; httponly". Process Loader_VER06.exe (2012)
First chance exception at $00629F8C. Exception class $C0000005 with message "access violation at 0x00629f8c: read of address 0x00000148". Process Loader_VER06.exe (2012)
- First chance exception at $7C812AFB. Exception class EOSError with message
"System Error.  Code: 123. Синтаксическая ошибка в имени файла, имени папки или метке тома".
Process Loader_VER06.exe (2012)
- First chance exception at $7C812AFB. Exception class EIdNotASocket with message
"Socket Error # 10038
Socket operation on non-socket.".
Process Loader_VER06.exe (2012)

В рабочем режиме, за счет подавления исключений, все это конечно не вылазит, но:
- закачиваются не все страницы(хотя все УРЛ валидные и функцией закачки закачиваются без вопросов)
- после закрытия Арр выводится сообщение о многочисленных маленьких утечках памяти

По теории потоки не должны пересекаться. каждый имеет свою память. вывод результата через КС. такое впечетление что потоки как то мешают друг другу
Внимание!!! Вопрос: в чем может быть причина появления исключений и утечки памяти именно в режиме многопотоковой закачки?


 
brother ©   (2012-12-27 11:45) [1]

> исключений и утечки памяти

исключения дают утечки...


 
Сергей М. ©   (2012-12-27 11:51) [2]

В упор не видно защиты глоб.ресурса gStore критической секцией.
Ты объект Cs вообще зачем создавал, не для этого ли как раз ?


 
Игорь Шевченко ©   (2012-12-27 11:51) [3]


> Вопрос: в чем может быть причина появления исключений и
> утечки памяти именно в режиме многопотоковой закачки?


Наверное в режиме отладки и строки, на которых проиходит исключение, показываются.

Не томи.


 
icWasya ©   (2012-12-27 11:55) [4]

Ну а в однопоточном режиме всё работает?
Ну то есть вот так
Procedure Loader(Url:string);
var ThreadLdr: TLoader;
begin
  ThreadLdr:=Tloader.Create(True);
  ThreadLdr.Priority:=tpNormal;  
  ThreadLdr.FreeOnTerminate:=True;
  ThreadLdr.Url:=Url;
  (*ThreadLdr.Start; вместо этого*)
  ThreadLdr.Execute;//<<==-- вот это
  ThreadLdr.Free;//<<==--
end;


 
Сергей М. ©   (2012-12-27 12:32) [5]


> вывод результата через КС


procedure TLoader.CallStore;
begin
  cs.Enter;
  try
    gStore.Add(Html); // вот теперь ресурс действительно защищен, никакие утечки теперь не грозят
  finally
    cs.Leave;
  end;
end;


 
Сергей М. ©   (2012-12-27 12:34) [6]

Разумеется "читающий" поток, тот который "выгребает" все это хозяйство из gStore, точно так же обязан входить в КС при этом.


 
anonims   (2012-12-27 12:52) [7]

В одном потоке все работает  => LoadPage не потокобезоасна. (использует и меняет не локальные данные).
function TLoader.LoadHtmlCode(const Url:string):string;
begin
Result:=LoadPage(Url); (*вызываем функцию загрузки страницы из uPageLoader*)
end;

unit uPageLoader;
interface
uses Classes, SysUtils, idHTTP, StrUtils, IdSSL, IdSSLOpenSSL;
  function LoadPage(const Url:string):string;  (*Основная функция Юнита*)

  var
  Loader:TidHTTP;
  SSL:TIdSSLIOHandlerSocketOpenSSL;

использование одного Loader, SSL для ВСЕХ потоков.


> тут много чего, но все работает, смотри в начало

тоже все глобальные объекты едины для всех потоков.


 
Pcrepair ©   (2012-12-27 14:03) [8]

anonims

> использование одного Loader, SSL для ВСЕХ потоков.

что ты имеешь ввиду? что нужно написать одинаковый код для скажем 10 потоков и для каждого прописать свой idHTTP, типа
idHTTP_1
idHTTP_2 и так далее и для каждого свое создание-уничтожение и все прочее?
++++++++++++++++++++++++++++++
Сергей М.

> Разумеется "читающий" поток, тот который "выгребает" все
> это хозяйство из gStore, точно так же обязан входить в КС
> при этом.

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

и еще вопрос: там перем Html прописана как свойство класса, хотя можно прописать ее ка переменную в ПАБЛИК. в чем разница? и как правильно
+++++++++++++++++++++++++++++
Игорь Шевченко
там выводит код из модулей ИНДИ
типа

unit IdSSLOpenSSL

procedure TIdSSLIOHandlerSocketOpenSSL.ConnectClient;
var
 LPassThrough: Boolean;
begin

 (*RLebeau 1/11/07:
 In case a proxy is being used, pass through any data from the base class unencrypted when setting up that connection.  
 ///В случае, если используется прокси-сервер, пройти через любые данные из базового класса, незашифрованные при создании связи
 We should do this anyway since SSL hasn"t been initialized yet!
 ///Мы должны сделать это в любом случае, поскольку SSL не была инициализирована
 *)

 LPassThrough := fPassThrough;
 fPassThrough := True;
 try
   inherited ConnectClient;  (*исключение*)
 finally
   fPassThrough := LPassThrough;
 end;
 DoBeforeConnect(Self);
 // CreateSSLContext(sslmClient);
 // CreateSSLContext(SSLOptions.fMode);
 StartSSL;
end;
Только в многопоточном режиме исключение?
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Socket Error 10056
модуль IdStack
сообщение:
procedure TIdStack.RaiseSocketError(AErr: integer);
begin
 (*
   RRRRR    EEEEEE   AAAA   DDDDD         MM     MM  EEEEEE    !!  !!  !!
   RR  RR   EE      AA  AA  DD  DD        MMMM MMMM  EE        !!  !!  !!
   RRRRR    EEEE    AAAAAA  DD   DD       MM MMM MM  EEEE      !!  !!  !!
   RR  RR   EE      AA  AA  DD  DD        MM     MM  EE
   RR   RR  EEEEEE  AA  AA  DDDDD         MM     MM  EEEEEE    ..  ..  ..

   Please read the note in the next comment.
 *)
 if AErr = Id_WSAENOTSOCK then begin
   // You can add this to your exception ignore list for easier debugging.
   // However please note that sometimes it is a true error. Your program
   // will still run correctly, but the debugger will not stop on it if you
   // list it in the ignore list. But for most times its fine to put it in
   // the ignore list, it only affects your debugging.
   raise EIdNotASocket.CreateError(AErr, WSTranslateSocketErrorMsg(AErr));
 end;
 (*
   It is normal to receive a 10038 exception (10038, NOT others!) here when
   *shutting down* (NOT at other times!) servers (NOT clients!).

   If you receive a 10038 exception here please see the FAQ at:
   http://www.IndyProject.org/

   If you insist upon requesting help via our email boxes on the 10038 error
   that is already answered in the FAQ and you are simply too slothful to
   search for your answer and ask your question in the public forums you may be
   publicly flogged, tarred and feathered and your name may be added to every
   chain letter / EMail in existence today."

   Otherwise, if you DID read the FAQ and have further questions, please feel
   free to ask using one of the methods (Carefullly note that these methods do
   not list email) listed on the Tech Support link at:
   http://www.IndyProject.org/

   RRRRR    EEEEEE   AAAA   DDDDD         MM     MM  EEEEEE    !!  !!  !!
   RR  RR   EE      AA  AA  DD  DD        MMMM MMMM  EE        !!  !!  !!
   RRRRR    EEEE    AAAAAA  DD   DD       MM MMM MM  EEEE      !!  !!  !!
   RR  RR   EE      AA  AA  DD  DD        MM     MM  EE
   RR   RR  EEEEEE  AA  AA  DDDDD         MM     MM  EEEEEE    ..  ..  ..
 *)
 raise EIdSocketError.CreateError(AErr, WSTranslateSocketErrorMsg(AErr));
end;
а вот что это значит и что с этим делать?


 
Сергей М. ©   (2012-12-27 14:16) [9]


> к описанным проблемам это пока не имеет отношения


"пока" может и не имеет, тебе виднее.
А потом поимеет - попросту забудешь про синхронизацию, как сейчас "забыл" про нее в CallStore.
Лучше таки сразу предусмотреть синхронизацию для всех потенциально возможных случаев. И обратить при этом внимание на TMultiReadExclusiveWriteSynchronizer как возможно более разумную альтернативу TCriticalSection.


 
RWolf ©   (2012-12-27 14:31) [10]


> что нужно написать одинаковый код для скажем 10 потоков
> и для каждого прописать свой idHTTP, типаidHTTP_1idHTTP_2
> и так далее и для каждого свое создание-уничтожение и все
> прочее?

ну, а как думаешь, данные глобального объекта idHTTP каким-то волшебным образом избегут разрушения, когда их модифицируют несколько потоков?
для каждого свой, конечно.


 
Сергей М. ©   (2012-12-27 14:42) [11]


> перем Html прописана как свойство класса, хотя можно прописать
> ее ка переменную в ПАБЛИК. в чем разница? и как правильно


А зачем она вообще нужна именно в описании класса ? Кто к ней обращается кроме членов самого класса TLoader ?
Судя по приведенному коду это вообще переменная временного назначения, место которой  - в стеке, т.е. среди локальных переменных подпрограмм.


 
Pcrepair ©   (2012-12-27 14:59) [12]


> А зачем она вообще нужна именно в описании класса ? Кто
> к ней обращается кроме членов самого класса TLoader ?

это рудимент предыдущих экспериментов

получается нужно писать код нескольких потоков, имеющих каждый свой idHTTP.Get и весь код обработки страницы, а не вызывать функции из доп. модулей? чтоб гарантированно не было исключений?

может тогда уже свой класс правильней написать? с использованием внутри этого класса потоков.
создавать потомок класса, передавать ему значение(УРЛ) + написать класс НАКОПИТЕЛЬ в который передавать асинхронно результат работы
с ООП знаком пока только теоритически


 
bems ©   (2012-12-27 15:04) [13]

вызывать функции других модулей можно, но нельзя при этом обращаться к общим данным без синхронизации.
например можно сделать функции LoadPage еще один параметр типа TidHttp и передавать в него экземпляр, с которым работает только вызывающий поток


 
Сергей М. ©   (2012-12-27 15:44) [14]


> а не вызывать функции из доп. модулей?


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


 
Pcrepair ©   (2012-12-27 17:26) [15]


> bems ©   (27.12.12 15:04) [13]
> вызывать функции других модулей можно, но нельзя при этом
> обращаться к общим данным без синхронизации.
> например можно сделать функции LoadPage еще один параметр
> типа TidHttp и передавать в него экземпляр, с которым работает
> только вызывающий поток


это типа

function TForm1.LoadPage(const S:string; idHttp: TidHttp):string;
begin
  idHttpLoad := TIdHTTP.Create(nil);
 try
   LoadPage := (AnsiLowerCase(idHttpLoad.Get(S)));
 finally
    idHttpLoad.Free;
 end;
end;


 
bems ©   (2012-12-27 18:56) [16]

типа
function LoadPage(const Url: String; IdHttp: TIdHttp): String;
begin
 Result := AnsiLowerCase(IdHttp.Get(Url))
end;

function TLoader.LoadHtmlCode(const Url: String): String;
begin
Result:=LoadPage(Url, FIdHttp)
end;
, где FIdHttp - поле TLoader, присваиваемое в конструкторе


 
Pcrepair ©   (2012-12-27 20:07) [17]

что то такую форму записи Result:=LoadPage(Url, FIdHttp) нигде в букварях не встречал

FIdHttp - это в

TLoader = class(TThread)
private
   FIdHttp:TidHTTP;

объявить?


 
bems ©   (2012-12-27 20:30) [18]

объявить. и в конструкторе присвоить FIdHttp := TIdHTTP.Create(nil);
в деструкторе соответственно освободить
что именно не встречал?


 
Pcrepair ©   (2012-12-27 21:31) [19]

вот это: (Url, FIdHttp)
но не будем отвлекаться на пустяки, итого нужно следующее

type
 TLoader = class(TThread)
 private
    FUrl:string;
    FIdHttp:TidHTTP;
 protected
   procedure Execute; override;
   function TLoader.LoadHtmlCode(const Url: String): String;
 public
   property Url: string read FUrl write FUrl;  (*свойство класа, доступное для всей программы*)
   constructor Create;
   destructor Destroy; override;
 end;

implementation
uses uPageLoader, uLoadPage, uGlobalVar;

constructor TLoader.Create(FIdHttp := TIdHTTP.Create(nil));
begin
  inherited Create(True);  (*Поток создаем в состоянии «Приостановлен»*)
  FreeOnTerminate := True; (* Поток освободит ресурсы при окончании работы*)  
  Self.Priority := tpNormal;  
end;

destructor TLoader.Destroy;
begin
 FreeAndNil(FIdHttp);
end;

function TLoader.LoadHtmlCode(const Url: String): String;
begin
 Result:=LoadPage(Url, FIdHttp)
end;

procedure TLoader.Execute;
var Code:string;
begin
   Code:=LoadHtmlCode(Url, IdHttp);
     CS.Enter;  (*вход в КС*)
       gStore.Add(Code); (*передаем результат в ГП*)
     Cs.Leave;  (*выход из КС*)
end;

end.
+++++++++++++++другой модуль++++++++++++++++++++
function LoadPage(const Url: String; IdHttp: TIdHttp): String;
begin
Result := AnsiLowerCase(IdHttp.Get(Url))
end;

а вызов потока останется прежний?


 
bems ©   (2012-12-27 21:45) [20]

constructor TLoader.Create(FIdHttp := TIdHTTP.Create(nil));
что это?
в теле конструктора присваивай, там же где FreeOnTerminate := True


 
bems ©   (2012-12-27 21:49) [21]

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


 
Pcrepair ©   (2012-12-27 22:04) [22]

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

SSL:=TIdSSLIOHandlerSocketOpenSSL.Create;
Loader.IOHandler:=SSL;

идут исключения в соответствующем модуле ИНДИ.
видимо надо усложнить:

constructor TLoader.Create;
begin
 inherited Create(True);  (*Поток создаем в состоянии «Приостановлен»*)
 FIdHttp := TIdHTTP.Create(nil);

          FSSL := TIdSSLIOHandlerSocketOpenSSL.Create;

 FreeOnTerminate := True; (* Поток освободит ресурсы при окончании работы*)  
 Self.Priority := tpNormal;  
end;


что касается вызова, там ведь тоже есть

ThreadLdr:=Tloader.Create(True); (*создаем поток, но не запускаем*)
   ThreadLdr.Priority:=tpNormal;    (*задать приортет нормальный*)
   ThreadLdr.FreeOnTerminate:=True;  (*самовыгрузка в конце потока*)
      (*передача в поток данных*)
   ThreadLdr.Url:=Url; (*передаем УРЛ в Поток*)
       (*запуск поток на выполнение*)
   ThreadLdr.Start;

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


 
bems ©   (2012-12-27 22:13) [23]

аа, не, после того как ты добавил конструктор без параметров, вызвать Create(True) уже нельзя

создавай просто ThreadLdr := Tloader.Create; а остальное у тебя уже внутри конструктора


 
Сергей М. ©   (2012-12-27 22:13) [24]


> в ООП пока не сильно


Вот это безобразие

> Create(FIdHttp := чегототам);

в сущности не имеет отношения к ООП


 
Pcrepair ©   (2012-12-27 22:22) [25]


> в сущности не имеет отношения к ООП

ага, разве TThread это не объект? со всеми втекающими и вытекающими

и в чем тут безобразие? поканкратнее пжалуйста


 
bems ©   (2012-12-27 22:32) [26]

в том что это не скомпилируется


 
Сергей М. ©   (2012-12-27 23:00) [27]


> в чем тут безобразие?


см. [26]


 
Pcrepair ©   (2012-12-27 23:16) [28]

не будем спотыкаться об уже пройденное, лучше продолжим:
Сама структура программы в принципе правильная?
- получаем список строк(УРЛ)
- запускаем конвейер потоков, передаем каждому свой УРЛ
- по закачке страницы, поток передает результат в ГлобПерем
- поток самоликвидируется
начинай сначала

получается что в начальный момент может одновременно запуститься практически от 50 до 200 потоков реально
складывается впечетление(по ошибке 10038 и 10056) что где то есть узкое место, всем потокам не хватает трафика и некоторые получают отказ. непонятно только как, временные интервалы в idHTTP для подключения к серверу и работы с сервером установлены в 50 сек.

или есть решения поумнее?


 
Сергей М. ©   (2012-12-27 23:19) [29]


> есть решения поумнее?


Объясни накой тебе аж 50 и более потоков ?


 
bems ©   (2012-12-27 23:31) [30]


> в начальный момент может одновременно запуститься практически
> от 50 до 200 потоков

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


> реально
> складывается впечетление(по ошибке 10038 и 10056) что где
> то есть узкое место, всем потокам не хватает трафика и некоторые
> получают отказ

в варианте без общего использования одного idHttp ошибки остаются?


 
Pcrepair ©   (2012-12-27 23:31) [31]

для полного использования трафика. в среднем скорость выдачи у серверов небольшая. если трафик к примеру 5000 кбит\сек, при средней скорости отдачи серверов 50 кбит\сек можно запускать до 100 потоков одновременно, ну чтоб провыдЫр не за так деньги получал


 
Pcrepair ©   (2012-12-27 23:36) [32]


> в варианте без общего использования одного idHttp ошибки
> остаются?

этот вариант еще не попробовал и вот почему: на самом деле функция в 19

+++++++++++++++другой модуль++++++++++++++++++++
function LoadPage(const Url: String; IdHttp: TIdHttp): String;
begin
 Result := AnsiLowerCase(IdHttp.Get(Url))
end;

IdHttp не содержит. LoadPage состоит из нескольких функций

unit uPageLoader;
interface
uses Classes, SysUtils, idHTTP, StrUtils, IdSSL, IdSSLOpenSSL;
   function LoadPage(const Url:string):string;  (*Основная функция Юнита*)
   procedure ErrorLog(Url:string);
   function LoadHtmlPage(const PageUrl:string):string;
   function DelJS(const Code:string):string;
   function RestoreFrame(const Code:string):string;
   function RestoreFullUrl(const Code:string; const RootUrl:string):string;
   function GetRandomUserAgent: string;
   var
   Loader:TidHTTP;
   SSL:TIdSSLIOHandlerSocketOpenSSL;

в том числе function LoadHtmlPage(const PageUrl:string):string; в которой как и есть idHTTP
Пока не совсем понятно как вызывать свой экземпляр idHTTP и SSL
Никаких идей нет?


 
Сергей М. ©   (2012-12-27 23:43) [33]


> чтоб провыдЫр не за так деньги получал


О как сурово)


 
bems ©   (2012-12-27 23:49) [34]

передавай через параметр как и в LoadPage.
ssl на момент вызова уже по идее должен быть присвоен в iohandler, поэтому ssl вообще можно убрать


 
Pcrepair ©   (2012-12-28 00:04) [35]


> ssl на момент вызова уже по идее должен быть присвоен в
> iohandler, поэтому ssl вообще можно убрать

некоторые утверждают что SSL:TIdSSLIOHandlerSocketOpenSSL; тоже получается как и idHTTP общее для всех потоков. и при отладке выскакивают исключения, которые указывают на модуль IdSSLOpenSSL(смотри[8])

в общем прийдется модуль переписать, под многопоточность


 
Pcrepair ©   (2012-12-28 00:05) [36]

а может попробовать в качестве загрузчика ICS


 
bems ©   (2012-12-28 00:11) [37]


> некоторые утверждают что SSL:TIdSSLIOHandlerSocketOpenSSL;
>  тоже получается как и idHTTP общее для всех потоков. и
> при отладке выскакивают исключения, которые указывают на
> модуль IdSSLOpenSSL

общий, но ты ж добавил в конструктор треда FSSL := TIdSSLIOHandlerSocketOpenSSL.Create;
вот остальные ssl убирай, и присваивай FidHttp.IoHandler еще перед вызовом LoadPage
ну и в uPageLoader передавай IdHttp везде через параметр


 
Германн ©   (2012-12-28 01:44) [38]


> Pcrepair ©   (28.12.12 00:05) [36]
>
> а может попробовать в качестве загрузчика ICS

Попытка - не пытка. Попробуй.
Лично я предпочитаю всегда ICS. Но я не занимался разработкой "поисковой машины". Так что мне больше нечего сказать.


 
Pcrepair ©   (2012-12-28 16:30) [39]

ну раз ты предпочитаешь ICS, тогда поведай миру о своем опыте, конкретно, есть ли в ICS:
- встроенная обработка перенаправления 301 и 302
- правильная кодировка кирилицы(так называемые кракрзябры вместо правльных букаф)
- возможность закачки HTTPs
- возможность установки нужного значения юзер-агент
- управление временем подключения к серверу и работы с сервером. ограничение в смысле

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


 
Pcrepair ©   (2012-12-28 19:22) [40]

а если вот так:

type
 TLoader = class(TThread) (*создаем свой класс на базе ПОТОК*)
 private
    FUrl:string; (*поле класса типа СТРОКА для чтения -записи данных*)
    FIdHttp:TidHTTP;
    FSSL:TIdSSLIOHandlerSocketOpenSSL;
 protected
   procedure Execute; override;
   function LoadHtmlCode(const Url: String):string; (*ФУНК загрузки страницы*)
 public
   property Url: string read FUrl write FUrl;  (*свойство класа, доступное для всей программы*)
   constructor Create;
   destructor Destroy; override;
 end;

implementation
uses Unit1, uLoadPage, uGlobalVar;

constructor TLoader.Create;
begin
 inherited Create(True); (*Поток создаем в состоянии «Приостановлен»*)
 FIdHttp := TIdHTTP.Create(nil);
 FSSL := TIdSSLIOHandlerSocketOpenSSL.Create;
 FreeOnTerminate := True; (* Поток освободит ресурсы при окончании работы*)
 Self.Priority := tpNormal;
end;

destructor TLoader.Destroy;
begin
 FreeAndNil(FIdHttp);
 FreeAndNil(FSSl);
end;

(*  28.12.2012 функция загрузки страницы прямо в коде потока*)
function TLoader.LoadHtmlCode(const Url: String):string;
begin
 FIdHttp.IOHandler:=FSSL;
 FIdHttp.HandleRedirects:=True;
 Result:=FIdHttp.Get(Url);
end;

procedure TLoader.Execute;
var Code:string;
begin
   Code:=LoadHtmlCode(Url);
     begin
      CS.Enter;  (*вход в КС*)
        try
          gStore.Add(Code); (*передаем результат в ГП*)
        finally
     Cs.Leave;  (*выход из КС*)
    end;
 end;
end;

end.

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



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

Форум: "Начинающим";
Текущий архив: 2013.09.15;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.61 MB
Время: 0.003 c
1-1313139731
vile
2011-08-12 13:02
2013.09.15
Русская кодировка в английской локали


4-1267176656
istok
2010-02-26 12:30
2013.09.15
Запуск процесса под юзером...


15-1365021003
Юрий
2013-04-04 00:30
2013.09.15
С днем рождения ! 4 апреля 2013 четверг


15-1365336685
Разведка
2013-04-07 16:11
2013.09.15
как создать сгенерировать UUID


2-1357022939
SKIPtr
2013-01-01 10:48
2013.09.15
команнда для перекрытия конструктора





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский