Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Delphi: TWebBrowser in background-thread

Is it possible to load a webpage in a TWebBrowser in a background thread?

When the application loads, I want to download a page from the web into a TWebBrowser, but I don't want to block the gui-thread.

Any suggestions?

Some clarifications:
The webbrowser-component is living on a form, and i want to display a page from the web. But I want to do all the downloading of that page in a background thread, so that loading a heavy page won't block the gui-thread.

I think I'm capable of writing threads in general.

like image 491
Vegar Avatar asked Jan 26 '26 21:01

Vegar


2 Answers

TWebBrowser already downloads stuff in a separate thread. Your program should already remain responsive while it's downloading. You can see this because a frequent pattern is to set the URL and then wait for the download to complete:

WebBrowser1.Navigate(...);
while WebBrowser1.Busy do
  Application.ProcessMessages;

That uses ProcessMessages, so I cannot in good faith recommend it. To be notified when the download is complete, instead of polling like that code does, handle the control's OnNavigateComplete2 event. Beware that the event may be fired for frames as well as the main page.

If you want to display the page, then your TWebBrowser control should not be in a separate thread anyway because it falls under the same rules as any other control used with the VCL. If you're just using the control to download a page, then TWebBrowser might be overkill. You could use Indy, or the operating system's built-in file-downloading functions. Those can be used in separate threads easily.

like image 144
Rob Kennedy Avatar answered Jan 29 '26 11:01

Rob Kennedy


I needed the same (to make automated screenshots of pages), and I started out with Rob's code. It didn't work for the pages that I was loading.. half of the time the busy flag was not set while clearly the page was not done yet.

After some research, this seemed to work:

while (webBrowser1.ReadyState <>  READYSTATE_COMPLETE) do
  Application.ProcessMessages;

where readystate is one of the following:

const READYSTATE_UNINITIALIZED = 0; // Default initialisation state.
const READYSTATE_LOADING = 1; // Object is currently loading data.
const READYSTATE_LOADED = 2; // Object has been initialised.
const READYSTATE_INTERACTIVE = 3; // User can interact with the object but loading has not yet finished.
const READYSTATE_COMPLETE = 4; // All of the object's data has been loaded.

The idea to use readystate came from here: http://gaskell.org/making-the-webbrowser-control-synchronous/

The readystate delphi constants were taken from here: http://www.cryer.co.uk/brian/delphi/twebbrowser/twebbrowser_properties.htm

like image 40
Wouter van Nifterick Avatar answered Jan 29 '26 13:01

Wouter van Nifterick



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!