Delphi TWebBrowser Memory Leak

爷,独闯天下 提交于 2019-12-04 16:54:36

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).

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.

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

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.

Rafae11o

To free up the memory, just initialize the new document:

(WebBrowser.Document as IPersistStreamInit).InitNew;
procedure TForm1.FreeMemory;
begin
    if Win32Platform = VER_PLATFORM_WIN32_NT then
    SetProcessWorkingSetSize(GetCurrentProcess, $FFFFFFFF, $FFFFFFFF);
end;

and call it from time to time

FreeMemory;
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!