问题
My application uses a TWebBrowser that loads a webpage. The problem is, after closing the form containing the TWebBrowser, the memory used is not freed. If I open and close the form, the memory just keeps on increasing.
Saw some post regarding calling SetProcessWorkingSetSize() or CoFreeUnusedLibrariesEx() to solve this issue, but I'm not sure if any of these are the correct solution.
Any idea how to free the memory used by TWebBrowser?
回答1:
QC#106829 describes one possible cause of memory leaks with TWebBrowser. Accessing Document
(and any other properties that are implemented via TOleControl.GetIDispatchProp
or TOleControl.GetIUnknownProp
) causes leaks because it calls AddRef without ever calling Release. As a workaround, you can manually call Release, or you can patch the VCL (see here), or you can avoid the problematic properties (for example, by using browser.DefaultInterface.Document
instead of browser.Document
).
回答2:
Using TWebBrowser does a lot of work behind the scenes, much of the same work a full instance of Internet Explorer would do. It is hidden from you, but still it's there and chances are it's unaccessible for us to force removing from memory. Check the memory usage before and between page loads, and test what happens when you call Navigate('about:blank');
. Also check whether your destructor gets called properly, and consider calling Navigate('about:blank');
from OnClose or OnCloseQuery. I found this does help the memory-situation a little bit.
回答3:
The best solution is STOP using TWebbrowser.
CEF4Delphi is a free library that uses Chrome instead of Internet Explorer. Always up to date and very efficient :
https://github.com/salvadordf/CEF4Delphi
回答4:
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}
To clear the memory, I use this function, found somewhere on the forums. It clears the "Working Set" much better than the SetProcessWorkingSetSize () method, but it is more difficult to call and it is registered in the Winapi.PsAPI unit. But, I noticed that both of these functions clean the "Working Set". And if you look at the "Allocated memory" column in the Task Manager, you can see that this parameter is not cleared. The "working set" of my application after cleaning can be reduced to 10 MB, but the all allocated memory will remain equal to 1.5 GB. And, in my opinion, this is what causes the error "Out of memory". And this error still appears if you look at heavy websites for a long time.
回答5:
To free up the memory, just initialize the new document:
(WebBrowser.Document as IPersistStreamInit).InitNew;
回答6:
procedure TForm1.FreeMemory;
begin
if Win32Platform = VER_PLATFORM_WIN32_NT then
SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
end;
and call it from time to time
FreeMemory;
来源:https://stackoverflow.com/questions/10224801/delphi-twebbrowser-memory-leak