Утечка памяти, неправильное использование потоков? - PullRequest
0 голосов
/ 01 апреля 2020

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

Это процедура, которая вызывается при клике

procedure TmainForm.scrollFrameClick(item:TEquipmentItem; itemFrame:TitemFrame);
begin
item.fullImage:=itemFrame.itemImage.Picture.Graphic;
setCurrentSearchItem(item);
end;

Процедура, вызывающая поток

procedure TmainForm.setCurrentSearchItem(item:TEquipmentItem);
begin

if not(assigned(searchResultTable)) then
  searchResultTable:=TItemHtmlTable.Create
else
  begin
    freeandnil(searchResultTable);
    searchResultTable:=TItemHtmlTable.Create;
  end;

if getDomTh<>nil then
  if getDomTh.Finished then
    begin
      getDomTh.Terminate;
      getDomTh.WaitFor;
      FreeAndNil(getDomTh);
    end
  else
    begin
      getDomTh.WaitFor;
      getDomTh.Terminate;
      FreeAndNil(getDomTh);
    end;

getDomTh:=TCreateDomThread.Create(false,'http://www.example.com/ru/items/'+inttostr(item.ID),searchResultTable.DomTree);

currentItemImage.Picture.Graphic:=item.fullImage;
itemNameLab.Caption:=item.ItemName;
itemTypeLab.Caption:=item.ItemTypeName;
itemSubtypeLab.Caption:=item.ItemSubtypeName;

/////////////////
// At this point i would call a thread and use the result from the "searchResultTable"
/////////////////

if getDomTh<>nil then
  if getDomTh.Finished then
    freeandnil(searchResultTable)
  else
    begin
      getDomTh.WaitFor;
      getDomTh.Terminate;
      FreeAndNil(getDomTh);
      freeandnil(searchResultTable);
    end;
end;

Это единица потока

unit threadUnit;

interface

uses System.Classes,System.SysUtils, parser;

type
  TCreateDomThread = class(TThread)
  private
    pDomTree:TDomTree;
    pUrl:string;
  public
    property tDomTree:TDomTree read pDomTree write pDomTree;
    property tUrl:string read pUrl write pUrl;
    constructor Create(suspended:boolean; Url:string; DomTree:TDomTree);
    procedure Execute; override;
  end;

implementation

uses main;


constructor TCreateDomThread.Create(suspended:boolean; Url:string; DomTree:TDomTree);
begin
  tDomTree:=DomTree;
  tUrl:=Url;
  inherited Create(suspended);
end;

procedure TCreateDomThread.Execute;
begin
    if Terminated then Exit;
    mainForm.getDomTree(tUrl, tDomTree);
end;
end.

DomTree-поиск

 procedure TmainForm.getDomTree(url:string; outputDomTree:TDomTree);
    var
      HtmlTxt: string;
    begin
      try
        HtmlTxt := IdHTTP1.Get(url);
        if not outputDomTree.RootNode.RunParse(HtmlTxt) then
          TThread.Queue(nil,procedure begin showmessage('Can'#39'tParse HTML!') end);
      except
        on E: Exception do
          TThread.Queue(nil,procedure begin ShowMessage(E.ClassName + ' : ' + E.Message); end);
      end;
    end;

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

РЕДАКТИРОВАТЬ:

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

Delphi снимок экрана диспетчера памяти

РЕДАКТИРОВАНИЕ 2: Обнаружена ошибка.

1 Ответ

0 голосов
/ 03 апреля 2020

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...