2009-03-12 5 views
3

Ist es möglich, eine Webseite in einem TWebBrowser in einem Hintergrund-Thread zu laden?Delphi: TWebBrowser im Hintergrund-Thread

Wenn die Anwendung geladen wird, möchte ich eine Seite aus dem Internet in einen TWebBrowser herunterladen, aber ich möchte den GUI-Thread nicht blockieren.

Irgendwelche Vorschläge?

Einige Erläuterungen:
Die Web-Browser-Komponente auf einem Formular leben, und ich will aus dem Internet eine Seite anzuzeigen. Aber ich möchte das ganze Herunterladen dieser Seite in einem Hintergrund-Thread machen, so dass das Laden einer schweren Seite den GUI-Thread nicht blockiert.

Ich denke, ich bin in der Lage, Threads im Allgemeinen zu schreiben.

Antwort

9

TWebBrowserbereits Downloads Zeug in einem separaten Thread. Dein Programm sollte beim Herunterladen bereits reagieren. Sie können dies, weil ein häufiges Muster die URL zu setzen und dann warten, bis der Download abgeschlossen:

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

Die ProcessMessages verwendet, so kann ich in gutem Glauben nicht empfehlen. Um benachrichtigt zu werden, wenn der Download abgeschlossen ist, führen Sie das Ereignis OnNavigateComplete2 des Steuerelements aus, anstatt wie der Code abzufragen. Beachten Sie, dass das Ereignis sowohl für Frames als auch für die Hauptseite ausgelöst werden kann.

Wenn Sie Anzeige wollen die Seite, dann TWebBrowser Kontrolle sollte nicht ohnehin in einem separaten Thread, weil sie nach den gleichen Regeln wie jede andere Kontrolle fallen mit der VCL verwendet. Wenn Sie das Steuerelement nur eine Seite verwenden, dann TWebBrowser möglicherweise übertrieben. Sie können Indy oder die im Betriebssystem integrierten Funktionen zum Herunterladen von Dateien verwenden. Diese können problemlos in separaten Threads verwendet werden.

+0

Das macht Sinn. Meine Anwendung stoppt für einige Sekunden, aber ich denke, ich muss dann einen anderen Grund dafür finden. – Vegar

+1

Die allgemeine Idee ist gut. Sie müssen nur ReadyState von Busy verwenden. Siehe meinen Kommentar für weitere Informationen .. –

1

Ich muss sagen, dass ich noch nie etwas Ähnliches versucht habe, aber ich nehme an, dass Sie auf Probleme stoßen werden.

Sie können mehrere Threads in einem Prozess haben, die alle Nachrichtenschleifen implementieren und die Nachrichten für die Fenster dieses Threads behandeln, aber alle Fenster sind an den Thread gebunden, der sie erstellt hat. Windows-Nachrichten werden immer in dem Thread behandelt, in dem das Fenster erstellt wurde. Sie können also möglicherweise eine Methode aus dem eingebetteten TWebBrowser-Steuerelement aus einem anderen Thread aufrufen, da dies jedoch das Senden einer Nachricht an das Webbrowserfenster erfordert in Ihrem GUI-Thread behandelt werden.

Weitere Informationen finden Sie in der Wikipedia-Artikel über Threading in COM und die Blog-Einträge von Raymond Chen über STA, wie this one.

3

Ich brauchte das gleiche (um automatisierte Screenshots von Seiten zu machen), und ich begann mit Robs Code. Es funktionierte nicht für die Seiten, die ich geladen habe .. Die Hälfte der Zeit, die die Flagge besetzt war, wurde nicht gesetzt, während die Seite noch nicht fertig war.

Nach einigen Recherchen, schien das zu funktionieren:

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

wo Readystate ist eine der folgenden Möglichkeiten: Readystate kam von hier

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. 

Die Idee zu verwenden: http://gaskell.org/making-the-webbrowser-control-synchronous/

Die ready-state Delphi-Konstanten wurden fr verwendet om hier: http://www.cryer.co.uk/brian/delphi/twebbrowser/twebbrowser_properties.htm