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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With