我的应用程序使用加载网页的TWebBrowser。问题是,在关闭包含TWebBrowser的表单后,使用的内存不会被释放。如果我打开并关闭表单,内存会不断增加。
看到一些关于调用SetProcessWorkingSetSize()或CoFreeUnusedLibrariesEx()的帖子来解决这个问题,但我不确定这些是否是正确的解决方案。
知道如何释放TWebBrowser使用的内存吗?
答案 0 :(得分:3)
QC#106829描述了使用TWebBrowser导致内存泄漏的一个可能原因。访问Document
(以及通过TOleControl.GetIDispatchProp
或TOleControl.GetIUnknownProp
实现的任何其他属性)会导致泄漏,因为它在不调用Release的情况下调用AddRef。作为解决方法,您可以手动调用Release,也可以修补VCL(see here),或者可以避免有问题的属性(例如,使用browser.DefaultInterface.Document
代替browser.Document
)
答案 1 :(得分:1)
使用TWebBrowser在幕后做了很多工作,很多相同的工作都是Internet Explorer的完整实例。它对你来说是隐藏的,但它仍然存在,并且很有可能我们无法强行从记忆中移除它。检查页面加载之前和之间的内存使用情况,并测试调用Navigate('about:blank');
时发生的情况。还要检查你的析构函数是否被正确调用,并考虑从OnClose或OnCloseQuery调用Navigate('about:blank');
。我发现这确实有助于记忆情况。
答案 2 :(得分:0)
最好的解决方案是使用TWebbrowser停止。
CEF4Delphi是一个使用Chrome而不是Internet Explorer的免费库。始终保持最新且非常高效:
答案 3 :(得分:-1)
Uses Winapi.PsAPI;
...
{$IFDEF WIN32}
procedure TForm1.MemoryFree;
var
HandleCaptureProcessus: THandle;
UnProcessus: TProcessEntry32;
PIDProcessus: THandle;
HandleProcessus: THandle;
NameOfProcess: string;
begin
PIDProcessus := 4294967295;
NameOfProcess := ExtractFileName(Application.ExeName);
HandleCaptureProcessus := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
UnProcessus.dwSize := SizeOf(TProcessEntry32);
Process32First(HandleCaptureProcessus, UnProcessus);
repeat
if UnProcessus.szExeFile = NameOfProcess then
begin
PIDProcessus := UnProcessus.th32ProcessID;
Break;
end;
until not Process32Next(HandleCaptureProcessus, UnProcessus);
if PIDProcessus = 4294967295 then
begin
CloseHandle(HandleCaptureProcessus);
exit;
end;
HandleProcessus := OpenProcess(PROCESS_ALL_ACCESS, False, PIDProcessus);
EmptyWorkingSet(HandleProcessus);
CloseHandle(HandleProcessus);
end;
{$ELSE}
procedure TForm1.MemoryFree;
begin
//**
end;
{$ENDIF}
要清除内存,我使用此功能,在论坛的某个地方找到。它比SetProcessWorkingSetSize()方法更好地清除“工作集”,但它更难调用并且它在Winapi.PsAPI单元中注册。 但是,我注意到这两个函数都清理了“工作集”。如果查看任务管理器中的“已分配内存”列,则可以看到此参数未被清除。清理后我的应用程序的“工作集”可以减少到10 MB,但所有分配的内存将保持等于1.5 GB。并且,在我看来,这是导致错误“内存不足”的原因。如果你长时间看重型网站,这个错误仍会出现。
答案 4 :(得分:-2)
要释放内存,只需初始化新文档:
(WebBrowser.Document as IPersistStreamInit).InitNew;
答案 5 :(得分:-2)
procedure TForm1.FreeMemory;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
end;
并不时给它打电话
FreeMemory;