Web Browser Control - Waiting for a Page to Load

I'm developing an application and I'm trying to keep it as object oriented as possible.  The application needs to collect information from web pages here and there and/or fill out forms on a website.

The problem I run into is this:  Traditionally.. most people will tell you that the best way to wait for a website to finish loading is this:

Do:
    Application.Doevents
Loop Until WB.IsBusy = False

This is all well and good and works, but firing doevents that many times causes a high cpu usage, and this does not seem practical.  Another alternative I have heard mentioned is to call System.Threading.Thread.Sleep(10).  This does lower the CPU usage, but it brings the entire thread to a complete stop, which is also not a practical solution.

WB.NewURL("www.google.com")
'Wait to recieve document complete event back from browser class
Do more stuff.

This SHOULD be able to happen, right?  It would be ridiculous to set up variables to keep track of what's currently happening and what to do next instead of just waiting until the browser is done loading with an event.  I'm just not sure how to make the particular function I'm in not process the next line of code until it recieves the event from my browser class without looping and using Application.Doevents.  Or maybe there's a better way to implement this?
MiStACoRnAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

PaulHewsCommented:
Simple example... Use the WebBrowser DocumentCompleted event.  (Note the test within to make sure it doesn't fire multiple times for frames.)
Public Class Form1
 
 
    Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
        WebBrowser1.Navigate("http://www.google.com")
    End Sub
 
    Private Sub WebBrowser1_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
 
        If e.Url = WebBrowser1.Url Then
            MsgBox("Document Completed")
        End If
 
    End Sub
End Class

Open in new window

0
MiStACoRnAuthor Commented:
This isn't what I mean.  I want to be able to call a new page from the middle of another function, and then have that function wait before it continues processing until the documentcomplete event fires.  If there a way to hold up on processing that next line without looping?  I just think it's really messy to write a billion functions based off events and keep track of what particular procedure is going on to handle what to do next.  Some of the procedures I'm going to build are going to use several websites in and of themselves.
0
PaulHewsCommented:
>it's really messy to write a billion functions based off events and keep track of what particular procedure is going on to handle what to do next.

I agree that it's messy, but the WebBrowser control uses an asynchronous model, and it has been my experience that it's better to go with the model exposed by the object.  The asynchronous model greatly reduces the cpu activity of your application.  However, it's easy enough to implement a loop that does what you want.

Do
    System.Threading.Thread.Sleep(10)
    Application.DoEvents()
Loop Until WB.IsBusy = False

Although your thread will be sleeping, it's for very small periods and prevents your application from hogging the CPU time.  Because of the DoEvents, it will still appear to be responsive to user actions.  You can play with the millisecond value: I've used up to 50 without any ill effect.
0
Cloud Class® Course: Certified Penetration Testing

This CPTE Certified Penetration Testing Engineer course covers everything you need to know about becoming a Certified Penetration Testing Engineer. Career Path: Professional roles include Ethical Hackers, Security Consultants, System Administrators, and Chief Security Officers.

MiStACoRnAuthor Commented:
Yeah if you look at my original post, these are things that I've already been implementing.  I'm just working on the newer version and I'd like to make it as event driven as possible.. but the amount of event handlers I'd have to create just seem absolutely ridiculous when compared to the loop.  I thought there might be a way to pause the function until an event triggers without looping.
0
PaulHewsCommented:
The problem is that each page handles the documentcompleted event differently, so there's a lot of branching code in your documentcompleted?

You can set up a class to handle certain pages...  WebBrowser and two buttons on new form
Public Class Form1
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim g As New WrapGoogle(WebBrowser1)
    End Sub
 
    Private Sub Button2_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles Button2.Click
        Dim y As New WrapYahoo(WebBrowser1)
    End Sub
End Class
 
Public Class WBWrapper
    Protected WithEvents mwb As WebBrowser
    Public Sub New(ByVal wb As WebBrowser)
        mwb = wb
    End Sub
    
End Class
 
Public Class WrapGoogle
    Inherits WBWrapper
    Public Sub New(ByVal wb As WebBrowser)
        MyBase.New(wb)
        AddHandler mwb.DocumentCompleted, AddressOf mwb_DocumentCompleted
        mwb.Navigate("http://www.google.com")
    End Sub
 
    Private Sub mwb_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) 
        mwb.Document.GetElementById("q").InnerText = "hello world"
        RemoveHandler mwb.DocumentCompleted, AddressOf mwb_DocumentCompleted
    End Sub
End Class
 
Public Class WrapYahoo
    Inherits WBWrapper
    Public Sub New(ByVal wb As WebBrowser)
        MyBase.New(wb)
        AddHandler mwb.DocumentCompleted, AddressOf mwb_DocumentCompleted
        mwb.Navigate("http://www.yahoo.com")
    End Sub
 
    Private Sub mwb_DocumentCompleted(ByVal sender As Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs)
        If e.Url = mwb.Url Then
            MsgBox(mwb.Document.Title)
        End If
        RemoveHandler mwb.DocumentCompleted, AddressOf mwb_DocumentCompleted
    End Sub
End Class

Open in new window

0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
Computer101Commented:
Forced accept.

Computer101
EE Admin
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.