This is the situation:
You should NEVER, EVER use Application.DoEvents()
in order to keep your UI responsive! Doing so is very bad practice and opens up the possibility of a lot of unexpected things happening, unless it is used correctly (which in most cases it isn't).
A good rule of thumb is: Any solution that utilizes Application.DoEvents()
is in 99.9% of the time a bad solution.
For more information about why DoEvents()
is so bad, refer to: Keeping your UI Responsive and the Dangers of Application.DoEvents.
I know all this might seem a bit extreme, but I can't really stress this enough. A lot of people are still using DoEvents()
today because it has been spread via some old forum and Stack Overflow posts, but it is infact not very good programming practice to use it because it is almost always used incorrectly.
Instead of using DoEvents()
, the WebBrowser
control has an event called DocumentCompleted which is raised every time a page (or a sub-part of a page, such as an iframe) is fully loaded.
The event can be subscribed to either statically:
Private Sub WebBrowser1_DocumentCompleted(sender As Object, e As WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted
If WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then
'Do stuff when the page has finished loading.
End If
End Sub
...or dynamically using Lambda Expressions:
Dim DocumentCompletedHandler As WebBrowserDocumentCompletedEventHandler = _
Sub(wsender As Object, we As WebBrowserDocumentCompletedEventArgs)
If WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then
'Do stuff when the page has finished loading.
'If you need to load another page and wait for it, just repeat the exact same code in here (but remember to rename the variables!).
RemoveHandler WebBrowser1.DocumentCompleted, DocumentCompletedHandler 'Remove the event handler (if you don't want this to be called twice).
End If
End Sub
AddHandler WebBrowser1.DocumentCompleted, DocumentCompletedHandler
WebBrowser1.Navigate("https://www.facebook.com/")
The good thing about the Lambda Expression solution is that it is much easier to use to add and remove multiple handlers when performing for instance web page automation.
EDIT:
If you're trying to perform automation I recommend the Lambda solution. That way you can a bit more dynamically add and remove handlers of the DocumentCompleted
event, depending on what you need to do.
To wait for an element with the specified text to appear, you can start a timer that iterates all the elements and check their InnerText
every time it ticks.
In the example below I've set the tick interval of the timer to 250 ms, thus it will check for the element approximately 4 times per second. You can adjust this as needed, but try not to use too small delays as that will increase CPU usage.
Dim WithEvents StepTwoWaitingTimer As New Timer With {.Interval = 250}
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim StepOneHandler As WebBrowserDocumentCompletedEventHandler = _
Sub(wsender As Object, we As WebBrowserDocumentCompletedEventArgs)
If WebBrowser1.ReadyState = WebBrowserReadyState.Complete Then
StepTwoWaitingTimer.Start() 'Start waiting for the required element to appear.
RemoveHandler WebBrowser1.DocumentCompleted, StepOneHandler
End If
End Sub
AddHandler WebBrowser1.DocumentCompleted, StepOneHandler
WebBrowser1.Navigate("your URL here")
End Sub
Private Sub StepTwoWaitingTimer_Tick(sender As Object, e As EventArgs) Handles StepTwoWaitingTimer.Tick
'Iterate each element with the "_54nh" class.
For Each Element As HtmlElement In WebBrowser1.Document.GetElementsByClassName("_54nh")
If Element.InnerText = "TEXTINSIDETHETAG" Then
'Element found. Click it and stop the timer.
Element.InvokeMember("click")
StepTwoWaitingTimer.Stop()
Exit For 'Stop the loop.
End If
Next
End Sub