我的应用程序使用加载网页的 TWebBrowser。问题是,关闭包含 TWebBrowser 的表单后,使用的内存没有被释放。如果我打开和关闭表单,内存就会不断增加。
看到一些关于调用 SetProcessWorkingSetSize() 或 CoFreeUnusedLibrariesEx() 来解决这个问题的帖子,但我不确定这些是否是正确的解决方案。
知道如何释放 TWebBrowser 使用的内存吗?
我的应用程序使用加载网页的 TWebBrowser。问题是,关闭包含 TWebBrowser 的表单后,使用的内存没有被释放。如果我打开和关闭表单,内存就会不断增加。
看到一些关于调用 SetProcessWorkingSetSize() 或 CoFreeUnusedLibrariesEx() 来解决这个问题的帖子,但我不确定这些是否是正确的解决方案。
知道如何释放 TWebBrowser 使用的内存吗?
使用 TWebBrowser 在幕后做了很多工作,与 Internet Explorer 的完整实例所做的大部分工作相同。它对你隐藏,但它仍然存在,我们可能无法强制从记忆中删除它。检查页面加载前后的内存使用情况,并测试调用Navigate('about:blank');
. 还要检查你的析构函数是否被正确调用,并考虑Navigate('about:blank');
从 OnClose 或 OnCloseQuery 调用。我发现这确实有助于记忆情况。
最好的解决方案是停止使用 TWebbrowser。
CEF4Delphi 是一个使用 Chrome 代替 Internet Explorer 的免费库。始终保持最新且非常高效:
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。而且,在我看来,这就是导致“内存不足”错误的原因。如果您长时间查看繁重的网站,此错误仍然会出现。
要释放内存,只需初始化新文档:
(WebBrowser.Document as IPersistStreamInit).InitNew;
procedure TForm1.FreeMemory;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
end;
并时不时地调用它
FreeMemory;