Page 1 of 1

CEF4 not close not release

Posted: Tue Apr 29, 2025 3:36 am
by Uefi1
Hello, it seems that in a single thread, Chromium closes successfully and releases memory, but in multiple threads, it does not close and does not release memory, leading to memory leaks. Please take a look; maybe I wrote something incorrectly:

Code: Select all

program Project2;

{$I cef.inc}

uses
  {$IFDEF DELPHI16_UP}
  Vcl.Forms,
  WinApi.Windows,
  {$ELSE}
  Forms,
  Windows,
  {$ENDIF }
  uCEFApplication, uCEFConstants,
  Unit2 in 'Unit2.pas' {Form2};

{$R *.res}

// CEF3 needs to set the LARGEADDRESSAWARE flag which allows 32-bit processes to use up to 3GB of RAM.
// If you don't add this flag the rederer process will crash when you try to load large images.

begin
  GlobalCEFApp := TCefApplication.Create;

  // In case you want to use custom directories for the CEF3 binaries, cache and user data.
  // If you don't set a cache directory the browser will use in-memory cache.
{
  GlobalCEFApp.FrameworkDirPath     := 'c:\cef';
  GlobalCEFApp.ResourcesDirPath     := 'c:\cef';
  GlobalCEFApp.LocalesDirPath       := 'c:\cef\locales';
  GlobalCEFApp.EnableGPU            := True;      // Enable hardware acceleration
  GlobalCEFApp.cache                := 'c:\cef\cache';
  GlobalCEFApp.UserDataPath         := 'c:\cef\User Data';
}

  // You *MUST* call GlobalCEFApp.StartMainProcess in a if..then clause
  // with the Application initialization inside the begin..end.
  // Read this https://www.briskbard.com/index.php?lang=en&pageid=cef
  if GlobalCEFApp.StartMainProcess then
    begin
      Application.Initialize;
      {$IFDEF DELPHI11_UP}
      Application.MainFormOnTaskbar := True;
      {$ENDIF}
      Application.CreateForm(TForm2, Form2);
      Application.Run;
    end;
    DestroyGlobalCEFApp;
end.

Code: Select all

unit Unit2;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, System.StrUtils,
  Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.SyncObjs, uCEFApplication, uCEFChromiumCore, 
  uCEFChromium, uCEFInterfaces, uCEFTypes, uCEFConstants;

type
  TForm2 = class(TForm)
    Button1: TButton;
    OpenDialog1: TOpenDialog;
    Button2: TButton;
    Button3: TButton;
    Label1: TLabel;
    Memo1: TMemo;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

type
th = class(TThread)
  private
  protected
  procedure ChromiumClose(Sender: TObject; const browser: ICefBrowser; var aAction : TCefCloseBrowserAction);
  procedure ChromiumAfterCreated(Sender: TObject; const browser: ICefBrowser);
  procedure ChromiumBeforeClose(Sender: TObject; const browser: ICefBrowser);
  procedure ChromiumLoadEnd(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; httpStatusCode: Integer);
  procedure Execute; Override;
  public
  constructor Сreate(createsuspended: boolean);
end;

var
  Form2: TForm2;
  cs:TCriticalSection;
  work:boolean=true;

implementation

{$R *.dfm}

{ th }

constructor th.Сreate(createsuspended: boolean);
begin
inherited Create(CreateSuspended);
FreeOnTerminate:=True;
end;

procedure th.ChromiumAfterCreated(Sender: TObject; const browser: ICefBrowser);
begin
  //form2.Memo1.Lines.Add('2');
  PostMessage(Browser.Host.OpenerWindowHandle, CEF_AFTERCREATED, 0, 0);
  //PostThreadMessage(Browser.Host.WindowHandle, CEF_AFTERCREATED, 0, 0);
end;

procedure th.ChromiumBeforeClose(Sender: TObject; const browser: ICefBrowser);
begin
  //form2.Memo1.Lines.Add('1');
  PostMessage(Browser.Host.OpenerWindowHandle, WM_QUIT, 0, 0);
  FreeAndNil(Sender);
  //PostThreadMessage(Browser.Host.WindowHandle, WM_QUIT, 0, 0);
end;

procedure th.ChromiumClose(Sender: TObject; const browser: ICefBrowser;
  var aAction: TCefCloseBrowserAction);
begin
  //form2.Memo1.Lines.Add('0');
  PostMessage(Browser.Host.OpenerWindowHandle, CEF_DESTROY, 0, 0);
  FreeAndNil(Sender);
  //PostThreadMessage(Browser.Host.WindowHandle, CEF_DESTROY, 0, 0);
end;

procedure th.ChromiumLoadEnd(Sender: TObject; const browser: ICefBrowser; const frame: ICefFrame; httpStatusCode: Integer);
begin
  Browser.Host.CloseBrowser(True);
end;

procedure th.Execute;
var
Chrome:TChromium;
begin
while work do begin
if work then begin
Chrome:=TChromium.Create(nil);
Chrome.DefaultUrl:=('https://');
Chrome.OnLoadEnd:=ChromiumLoadEnd;
Chrome.OnAfterCreated:=ChromiumAfterCreated;
Chrome.OnBeforeClose:=ChromiumBeforeClose;
Chrome.OnClose:=ChromiumClose;
Chrome.CreateBrowser(nil);
end;
end;
end;

procedure TForm2.Button1Click(Sender: TObject);
var
i:integer;
begin
cs:=TCriticalSection.Create;
//for i:=1 to 100 do
th.Create(False);
end;

procedure TForm2.Button2Click(Sender: TObject);
begin
work:=False;
end;
end.

Re: CEF4 not close not release

Posted: Tue Apr 29, 2025 12:42 pm
by salvadordf
Hi,

See this example :
https://github.com/salvadordf/CEF4Delphi/blob/master/demos/Delphi_VCL/WebpageSnapshot/uCEFBrowserThread.pas

Several demos like WebpageSnapshot or ConsoleBrowser2 use a browser in a thread. Use those examples as a template for your application.

Re: CEF4 not close not release

Posted: Wed Apr 30, 2025 12:02 am
by Uefi1
salvadordf wrote: Tue Apr 29, 2025 12:42 pm Hi,

See this example :
https://github.com/salvadordf/CEF4Delphi/blob/master/demos/Delphi_VCL/WebpageSnapshot/uCEFBrowserThread.pas

Several demos like WebpageSnapshot or ConsoleBrowser2 use a browser in a thread. Use those examples as a template for your application.
Hello, I reviewed all your demos, and they are written in an inaccessible and unclear way. To understand them, I would need to spend a year working with them. So please let me know what is wrong with my code right away so I can fix it all.