Delphi TWebBrowser内存泄漏
我的应用程序使用TWebBrowser加载网页。问题是,在关闭包含TWebBrowser的表单后,使用的内存没有被释放。如果我打开和关闭表单,内存就会不断增加 看到一些关于调用SetProcessWorkingSetSize()或cofreeunsedLibrarieSex()来解决此问题的帖子,但我不确定这些是否是正确的解决方案Delphi TWebBrowser内存泄漏,delphi,delphi-2009,twebbrowser,Delphi,Delphi 2009,Twebbrowser,我的应用程序使用TWebBrowser加载网页。问题是,在关闭包含TWebBrowser的表单后,使用的内存没有被释放。如果我打开和关闭表单,内存就会不断增加 看到一些关于调用SetProcessWorkingSetSize()或cofreeunsedLibrarieSex()来解决此问题的帖子,但我不确定这些是否是正确的解决方案 知道如何释放TWebBrowser使用的内存吗 使用TWebBrowser在幕后做了大量工作,大部分工作与完整的Internet Explorer实例相同。它对你是隐
知道如何释放TWebBrowser使用的内存吗 使用TWebBrowser在幕后做了大量工作,大部分工作与完整的Internet Explorer实例相同。它对你是隐藏的,但它仍然在那里,我们很可能无法从记忆中强行移除它。检查页面加载之前和加载之间的内存使用情况,并测试调用
Navigate('about:blank')时发生的情况代码>。还检查析构函数是否被正确调用,并考虑调用<代码>导航(“关于:空白”);代码>来自OnClose或OnCloseQuery。我发现这确实有助于改善内存状况。要释放内存,只需初始化新文档:
(WebBrowser.Document as IPersistStreamInit).InitNew;
并时不时地给它打电话
FreeMemory;
描述TWebBrowser内存泄漏的一个可能原因。访问文档
(以及通过TOleControl.GetIDispatchProp
或TOleControl.GetIUnknownProp
实现的任何其他属性)会导致泄漏,因为它调用AddRef而从未调用Release。作为一种解决方法,您可以手动调用Release,或者修补VCL(),或者可以避免出现问题的属性(例如,使用browser.DefaultInterface.Document
而不是browser.Document
)
为了清除内存,我使用了这个功能,可以在论坛上找到。它清除“工作集”的效果比SetProcessWorkingSetSize()方法好得多,但调用起来更困难,并且它注册在Winapi.PsAPI单元中。
但是,我注意到这两个函数都会清理“工作集”。如果您查看任务管理器中的“已分配内存”列,可以看到此参数未被清除。清理后,我的应用程序的“工作集”可以减少到10 MB,但所有分配的内存将保持等于1.5 GB。在我看来,这就是导致错误“内存不足”的原因。如果你长时间浏览大量网站,这个错误仍然会出现。最好的解决方案是停止使用TWebbrowser
CEF4Delphi是一个使用Chrome而不是Internet Explorer的免费图书馆。始终保持最新且非常高效:
我认为您可能错误地解释了您用来收集这些统计数据的任何内容。堆分配器非常复杂,在需要释放内存之前,它们通常会保留内存。如果系统有足够的可用内存,为什么要花时间将它返回操作系统,而你可以免费保留它。你是如何关闭(和打开)表单的,它是否被任何东西释放了?如果你在不加载网页的情况下打开和关闭表单,你是否仍然存在内存问题?你可能会发现这样一个泄漏应用程序的例子。即使以TWebBrowser
作为组件的表单被释放,线程仍会保持运行,并且每个新实例都会创建新的线程(因此内存消耗会增加)。我还没有找到解决方案,我尝试了很多方法,包括cofreeunsedlibrariesex
,导航到about:blank
,没有任何帮助。这是一个严重的问题,因为创建多个表单实例需要耗费大量的系统资源。我的建议是隐藏表单,而不是发布,因为它在这里似乎没有效果;它只是“压缩”使用的内存,但在新导航后,以前使用的所有巨大内存都会重新定位。此解决方案不起作用,内存仍在不断增加。使用browser.DefaultInterface.Document
而不是browser.Document
解决了我的内存泄漏问题。感谢您在Delphi10.0中修复了这个TOleControl
bug。
FreeMemory;
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}