Добрый день.
Есть функция вида 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)
В рабочем режиме, за счет подавления исключений, все это конечно не вылазит, но:
- закачиваются не все страницы(хотя все УРЛ валидные и функцией закачки закачиваются без вопросов)
- после закрытия Арр выводится сообщение о многочисленных маленьких утечках памяти
По теории потоки не должны пересекаться. каждый имеет свою память. вывод результата через КС. такое впечетление что потоки как то мешают друг другу
Внимание!!! Вопрос: в чем может быть причина появления исключений и утечки памяти именно в режиме многопотоковой закачки?