您应该永远不要使用 Application.DoEvents() 以保持您的 UI 响应!这样做是非常糟糕的做法,并且可能会发生很多意想不到的事情,除非它被正确使用(在大多数情况下不是这样)。
一个好的经验法则是:任何使用Application.DoEvents() 的解决方案在 99.9% 的情况下都是糟糕的解决方案。
有关DoEvents() 为何如此糟糕的更多信息,请参阅:Keeping your UI Responsive and the Dangers of Application.DoEvents。
我知道这一切可能看起来有点极端,但我真的不能强调这一点。很多人今天仍在使用DoEvents(),因为它已经通过一些旧论坛和 Stack Overflow 帖子传播,但实际上使用它并不是很好的编程习惯,因为它几乎总是使用错误。
WebBrowser 控件没有使用 DoEvents(),而是有一个名为 DocumentCompleted 的事件,每次页面(或页面的子部分,例如 iframe)完全加载时都会引发该事件。
事件可以静态订阅:
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
...或动态使用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/")
Lambda 表达式解决方案的好处在于,在执行网页自动化等实例时,它更易于添加和删除多个处理程序。
编辑:
如果您尝试执行自动化,我建议您使用 Lambda 解决方案。这样您就可以更动态地添加和删除 DocumentCompleted 事件的处理程序,具体取决于您需要做什么。
要等待具有指定文本的元素出现,您可以启动一个迭代所有元素的计时器,并在每次计时时检查它们的InnerText。
在下面的示例中,我将计时器的滴答间隔设置为 250 毫秒,因此它将每秒检查大约 4 次元素。您可以根据需要进行调整,但尽量不要使用太小的延迟,因为这会增加 CPU 使用率。
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