Page 1 of 2

Application hangs when finished.

Posted: Thu Sep 21, 2017 10:23 pm
by marcoscdoni
Hello Salvador,

Sorry, but I would like to clarify a question. When I create instances of TChromiumWindow at runtime, closing the application hangs the same.

What would be the correct way to free the browsers instantiated so that the application does not crash?

Thank you!

Re: Application hangs when finished.

Posted: Fri Sep 22, 2017 8:20 am
by salvadordf
Hi,

Take a look at the ToolboxBrowser and MDIBrowser demos. The comments explain how to free the browsers safely.

Edit : I forgot to say that it's recommended to delete the contents of the cache and cookies custom directories in case of hard crashes.

Re: Application hangs when finished.

Posted: Fri Sep 22, 2017 3:01 pm
by marcoscdoni
Hello Salvador,

Thank you for your quick answer.

What I'm not understanding is that when I try to debug with the GlobalCEFApp.SingleProcess property as true or false there is no error closing the application.

But in the release version I'm having these access violation issues when I close the application.

One question, I'm creating TChromiumWindow objects at runtime and I'm not using the "TCEFWindowParent1" control. I'm setting a tabSheet as parent. So, I ask, could this be the problem? If so, why not the access violation does not happen in debug mode?

Re: Application hangs when finished.

Posted: Fri Sep 22, 2017 3:28 pm
by salvadordf
Hi,
marcoscdoni wrote: Fri Sep 22, 2017 3:01 pm What I'm not understanding is that when I try to debug with the GlobalCEFApp.SingleProcess property as true or false there is no error closing the application.
But in the release version I'm having these access violation issues when I close the application.
The single process mode is for debugging purposes only and it's not supported. Use it only if you want to make your life a little easier when your code is executed in different processes.

There are some debugging instructions here :
https://www.briskbard.com/index.php?lang=en&pageid=cef
marcoscdoni wrote: Fri Sep 22, 2017 3:01 pm One question, I'm creating TChromiumWindow objects at runtime and I'm not using the "TCEFWindowParent1" control. I'm setting a tabSheet as parent. So, I ask, could this be the problem? If so, why not the access violation does not happen in debug mode?
When you create and destroy browsers at runtime you have to follow the destruction steps described in the MDIBrowser or ToolBoxBroser demos.

Please read the comments in these units :
https://github.com/salvadordf/CEF4Delph ... ldForm.pas (line 93)
https://github.com/salvadordf/CEF4Delph ... inForm.pas (line 96)

TCEFChromeWindow is just a descendant of TCEFWindowParent with a TChromium child. I created TCEFChromeWindow to be used in much simpler applications.

In your case I would recommend to adapt the MDIBrowser code into your application.

Re: Application hangs when finished.

Posted: Sat Sep 23, 2017 9:54 am
by salvadordf
Hi,

I added a new demo to CEF4Delphi that handles multiple tab sheets and tchromium browsers. It's called "TabbedBrowser".

Please download it, read the code comments and use it as a reference if this is what you needed for your app.

Re: Application hangs when finished.

Posted: Tue Nov 14, 2017 2:15 pm
by Det20
I try it like you do, but my app hangs sometimes, too. And can't find the problem.

Re: Application hangs when finished.

Posted: Tue Nov 14, 2017 8:00 pm
by salvadordf
Please, give me all the details you can.

Is it crashing when the application is closing the main form ?
Did you follow all the steps described in the MDIBrowser to close all the browsers in your app before closing the main form ?
Can you replicate the error with one of the demos ?

Edit : Remember to clear the cache directory after a crash.

Re: Application hangs when finished.

Posted: Wed Nov 15, 2017 9:44 am
by Det20
I use TMS components and AlphaSkin/AlphaControls in my application.
What i do in my source is:

In DPR:

Code: Select all

uses ... uCEFApplication

    GlobalCEFApp := TCefApplication.Create;
    GlobalCEFApp.DeleteCache   := true;
    GlobalCEFApp.DeleteCookies := true;
    GlobalCEFApp.FlashEnabled  := true;
    GlobalCEFApp.EnableSpeechInput := false;
    GlobalCEFApp.EnableMediaStream := true;

    If GlobalCEFApp.StartMainProcess then begin
      Application.Initialize;
      Application.MainFormOnTaskbar := True;
      Application.Title := 'xxx';
      Application.CreateForm(TfrmMain, frmMain);
      Application.Run;
    end;
    FreeAndNil(GlobalCEFApp);
In Main.PAS. Somewhere in the Code:

Code: Select all

// Somewhere in the Code
Chromium1.CreateBrowser(CEFWindowParent1);

Code: Select all

procedure TfrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
  // BTW: What exactyle mean the Parameter?
  Chromium1.CloseBrowser(true);
end;

Re: Application hangs when finished.

Posted: Wed Nov 15, 2017 2:23 pm
by salvadordf
There are 2 options :
  • 1- You only create 1 TChromium and it's destroyed at the same time the app closes.
  • 2- You create several TChromium components.
For the first case you don't have to call "CloseBrowser". You should let the normal application destruction handle your TChromium.

For the second case you should follow the complete destruction sequence described in the MDIBrowser.
This is what the uChildForm.pas file has in the comments :

Code: Select all

// Destruction steps
// =================
// 1. FormCloseQuery calls TChromium.CloseBrowser
// 2. TChromium.OnClose sends a CEFBROWSER_DESTROY message to destroy CEFWindowParent1 in the main thread.
// 3. TChromium.OnBeforeClose sets FCanClose := True and sends WM_CLOSE to the form.
Every TChildForm has 2 variables to control all these steps : FCanClose and FClosing.

In this case, you need to add all the code in :
  • TChildForm.FormCloseQuery : The first time this function is called you set CanClose to False and then call TChromium.CloseBrowser.
  • TChildForm.Chromium1Close : This event is triggered because you called TChromium.CloseBrowser and it's called from a different thread. This is the moment to send a CEFBROWSER_DESTROY message to the main form to destroy TCEFWindowParent in the main thread.
  • TChildForm.BrowserDestroyMsg : This is the form function that handles the CEFBROWSER_DESTROY message and here you can destroy TCEFWindowParent safely. This destruction will trigger the TChromium.OnBeforeClose event.
  • TChildForm.Chromium1BeforeClose : This event is triggered because you destroyed TCEFWindowParent and it's the moment to set FCanClose := True and send WM_CLOSE to the form if this was the last TChromium component.
You should close the application when you receive the last TChromium.OnBeforeClose.
If you do it before, you may have random crashes when the application closes.

CEF3 has improved in the last months and sometimes you don't need to follow all this sequence.
The TabbedBrowser don't crash when you have several tabs and you close the app but the MDIBRowser and ToolBoxBrowser need to implement all these steps.

About the CloseBrowser parameter, this is what the CEF3 sources say :

Code: Select all

  ///
  // Request that the browser close. The JavaScript 'onbeforeunload' event will
  // be fired. If |force_close| is false (0) the event handler, if any, will be
  // allowed to prompt the user and the user can optionally cancel the close. If
  // |force_close| is true (1) the prompt will not be displayed and the close
  // will proceed. Results in a call to cef_life_span_handler_t::do_close() if
  // the event handler allows the close or if |force_close| is true (1). See
  // cef_life_span_handler_t::do_close() documentation for additional usage
  // information.
  ///
In short, if you set aForceClose to True, you're ignoring any javascript code that may ask "are you sure you want to close this tab?" or something similar. When you call CloseBrowser(False) then you have to handle those dialog boxes.

Re: Application hangs when finished.

Posted: Wed Nov 15, 2017 2:44 pm
by Det20
I only have one TChromium and one TCEFWindowParent on the Form. It's a single form, not a MDI form.
I use "Chromium1.CreateBrowser(CEFWindowParent1)". I think, if i use "CreateBrowser" i have to Call "CloseBrowser"?

So Case 1 should be my case, but it crash ... Do i need to wait, until "Close" event is triggered?