【发布时间】:2020-04-01 17:08:33
【问题描述】:
我第一次尝试使用线程,但不知道为什么会出现内存泄漏,线程滥用的原因,或者导致我愚蠢而忘记释放某些东西,但在这一点上,我不知道, 是哪一个(或两者)。
这是点击时调用的过程
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;
如果您点击几次,taskmanager 会显示已提交的内存一直在增加。 我对调试没有运气,任何建议将不胜感激。
编辑:
所以有一堆TDomTree 不是免费的,但我不明白,从哪里导致线程按预期被破坏
Delphi memory manager screenshot
编辑 2: 发现错误。
【问题讨论】:
-
您有什么证据表明内存泄漏? (不要依赖您认为 TaskMan 可能会告诉您的内容。)
-
好吧,既然我可以点击 50 次并使用 100+ mb 的内存,我想,我可以称之为泄漏
-
与内存泄漏无关,但
setCurrentSearchItem的前七行可以单独替换为else分支中的两行。如果X是nil,那么做X.Free(因此FreeAndNil(X))是完全安全的。那是因为X.Free基本上是if Assigned(X) then X.Destroy。 -
好的,谢谢
标签: multithreading delphi memory