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

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

Проблемы с потоками при закачке страниц


Страницы:   1 2 3 4 5

Pcrepair ©   (2012-12-27 11:20:00) 

Добрый день.
Есть функция вида 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)

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

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


Pcrepair   (2012-12-30 22:40:00) [41]

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

unit uPageLoader;
interface
uses idHTTP, SysUtils;
 function LoadPage(const Url:string):string;
 var idHttp:TidHTTP;
implementation

function LoadPage(const Url:string):string;
begin
 idHttp:=TidHttp.Create(nil);
    Result:=idHttp.Get(Url);
 FreeAndNil(idHttp);
end;
end.


похоже это косяк ИНДИ


DVM   (2012-12-30 22:36:00) [42]


> Pcrepair ©   (30.12.12 22:21) [58]


> вообще то через это свойство в поток передается УРЛ, как
> оно не может быть public?

А кто говорил, что оно не может быть паблик? На здоровье пусть будет паблик, но оно не потокобезопасно. Сделать потокобезопасное свойство не проблема если что.


> к gStore любые обращения идут через CS, это не сложно

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


Pcrepair   (2012-12-30 22:21:00) [43]

Игорь Шевченко

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

SysUtils

procedure ConvertErrorFmt(ResString: PResStringRec; const Args: array of const); local;
begin
 raise EConvertError.CreateResFmt(ResString, Args); (*тут*)
end;


Call stack -THread 4064

:7c812afb kernel32.RaiseException + 0x52
System.SysUtils.ConvertErrorFmt($4129A8,(...))
System.SysUtils.StrToInt('')
IdGlobal.IndyStrToInt('')
IdGlobalProtocols.RawStrInternetToDateTime('',0)
IdGlobalProtocols.GMTToLocalDateTime('')
IdHTTPHeaderInfo.TIdEntityHeaderInfo.ProcessHeaders
IdHTTPHeaderInfo.TIdResponseHeaderInfo.ProcessHeaders
IdHTTP.TIdHTTPProtocol.RetrieveHeaders(???)
IdHTTP.TIdCustomHTTP.DoRequest(???,' http://www.xard.ru/post/10305/',nil,$16D3B20,(...))
IdHTTP.TIdCustomHTTP.Get(' http://www.xard.ru/post/10305/',$16D3B20,(...))
IdHTTP.TIdCustomHTTP.Get(' http://www.xard.ru/post/10305/',(...))
IdHTTP.TIdCustomHTTP.Get(' http://www.xard.ru/post/10305/')
uThreadLoader.TLoader.LoadHtmlCode(' http://www.xard.ru/post/10305/')
uThreadLoader.TLoader.LoadPage(' http://www.xard.ru/post/10305/')
uThreadLoader.TLoader.Execute
System.Classes.ThreadProc($16FE0A0)
System.ThreadWrapper($16E13E0)
:7c80b729 ; C:\WINDOWS\system32\kernel32.dll

причем на каждом УРЛ исключение выскакивает дважды
++++++++++++++++++++++++++++++++++++++++++++++++++

> это свойство не потокобезопасно, к нему есть обращения одновременно
> на изменение и чтение из разных потоков?

вообще то через это свойство в поток передается УРЛ, как оно не может быть public? потом значение из этого поля идет в поток и тд...
в конвейре запуска потоков, каждому потоку передается свое значение, после чего поток его обрабатывает. это все
---------------
к gStore любые обращения идут через CS, это не сложно


DVM   (2012-12-29 23:28:00) [44]


> Pcrepair ©   (29.12.12 22:52) [53]
> да уже второй день как есть синхронизация, всего к всему

Да ладно, не верю. Более чем уверен, что вот к этому твоему gStore есть не защищенные обращения.


DVM   (2012-12-29 23:26:00) [45]


> Pcrepair ©   (28.12.12 19:22) [40]


>  public
>    property Url: string read FUrl write FUrl;  (*свойство
> класа, доступное для всей программы*)

это свойство не потокобезопасно, к нему есть обращения одновременно на изменение и чтение из разных потоков?


Игорь Шевченко   (2012-12-29 23:12:00) [46]

Pcrepair ©   (29.12.12 20:56) [45]

> для всех пишет одно и то же(в режиме отладки):
> First chance exception at $7C812AFB. Exception class EConvertError
> with message ''''' is not a valid integer value'. Process
> Project.exe (2728)
> Что это непонятно


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

Не томи.


Сергей М.   (2012-12-29 22:59:00) [47]

Если однопоточнаязагрузка (о чем тебе еще в [4] намекнул Вася) этих страниц не вызывает исключения, можешь смело забить на него.
В противном случае ССЗБ.


Pcrepair   (2012-12-29 22:52:00) [48]

да уже второй день как есть синхронизация, всего к всему
это фигня вылезает на 2-х страницах, всегда одних и тех же, из 200 в списке

кстати, повторюсь, страницы все равно закачиваются, те самые на кторых выскакивает исключение (в режиме отладки только)


Сергей М.   (2012-12-29 22:41:00) [49]


> Что это непонятно


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


Медвежонок Пятачок   (2012-12-29 22:36:00) [50]

ну значит и эксепшена нет. Наверное тебе привиделось.


Pcrepair   (2012-12-29 22:30:00) [51]

это ты так очень иносказательно, почти как дедушко Крылов, намекаешь что исключение связано с использованием системной функции?

кстати, нет там нигде StrToInt. и IntToStr то же нет


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

А кто тогда делает  strtoint? Дедушко мороз?


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

А кто тогда делает  strtoint? Дедушко мороз?


Pcrepair   (2012-12-29 21:18:00) [54]

нет в IdHTTP.TIdCustomHTTP.Get никакой обработки.


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

Что что. Это твоя обработка текста страницы. К загрузке отношения не имеющая.


Pcrepair   (2012-12-29 20:56:00) [56]

ну что все уже празднуют? вопросы еще остались

сделал все функции и процедуры методами класса, из доп модулей ничего не вызывается
ошибки остались, только для этих страниц:
----------------это все из отладчика----------------------------------------
IdHTTP.TIdCustomHTTP.Get(' http://www.xard.ru/post/10305/',(...))
IdHTTP.TIdCustomHTTP.Get(' http://www.electrosad.ru/Electronics/PP.htm',$16D3A00,(...))
uThreadLoader.TLoader.LoadHtmlCode(' http://www.xard.ru/post/10305/')

для всех пишет одно и то же(в режиме отладки):
First chance exception at $7C812AFB. Exception class EConvertError with message ''''' is not a valid integer value'. Process Project.exe (2728)
Что это непонятно, так как страницы закачиваются

в остальном все хорошо, утечки памяти нет, закачиваются все страницы


Германн   (2012-12-29 02:30:00) [57]

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


Pcrepair   (2012-12-28 21:45:00) [58]

Удалено модератором
Примечание: Правила форума надо уважать


Pcrepair   (2012-12-28 21:02:00) [59]

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


Сергей М.   (2012-12-28 20:05:00) [60]


> constructor TLoader.Create;
> ..
>  Self.Priority := tpNormal; // эта строчка гуляет по Тырнету в миллионах экз-рах, ты ее позорно сдул  - и какое отношение к себе при этом ты изволишь желать ?
>..
> end;


Страницы:   1 2 3 4 5

Наверх

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