如何创建不停止WebBrowser加载的等待计时器? [英] How to create a waiting timer that does not stop the loading of a WebBrowser?

查看:110
本文介绍了如何创建不停止WebBrowser加载的等待计时器?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是这种情况:




  • 我在VB .NET项目中有一个web浏览器

  • 我在Facebook上登录

  • 我必须等待页面/ javascript输出完成加载



我想设置一个等待秒数的计时器,以不停止浏览器的加载。



此解决方案似乎不起作用:

 在WebBrowser1.ReadyState<>中执行WebBrowserReadyState.Complete 
Application.DoEvents()
循环


解决方案

您应该 从不,永远 使用 Application.DoEvents()来保持用户界面反应灵敏!这样做是 非常不好的做法 ,并且打开了发生许多意外事件的可能性,除非正确使用(在大多数情况下不是这样)。 / p>

一个好的经验法则是:使用 Application.DoEvents()的任何解决方案都占99.9%的时间一个 错误的解决方案



有关为什么 DoEvents()太糟糕了,请参考: 保持UI响应和Application.Doangers的危险。DoEvents



我知道所有这些似乎都太极端了,但是我真的不能对此施加太大压力。今天很多人仍在使用 DoEvents(),因为它已经通过一些旧论坛和Stack Overflow帖子进行了传播,但实际上使用它并不是很好的编程习惯因为几乎总是错误地使用它们。






而不是使用 DoEvents() WebBrowser 控件有一个名为 DocumentCompleted ,该值在每次页面(或页面的子部分,例如iframe)完全加载时引发。



事件可以静态地订阅:

  Private Sub WebBrowser1_DocumentCompleted(Sender As Object,e As WebBrowserDocumentCompletedEventArgs)处理WebBrowser1.DocumentCompleted 
如果WebBrowser1.ReadyState = WebBrowserReadyState.Complete然后
‘在页面加载完成后执行操作。
End If
End Sub

...或动态使用 Lambda表达式

  Dim DocumentCompletedHandler As WebBrowserDocumentCompletedEventHandler = _ 
Sub(wsender作为对象,我们作为WebBrowserDocumentCompletedEventArgs )
如果WebBrowser1.ReadyState = WebBrowserReadyState.Complete然后
'在页面加载完成后执行操作。
’如果需要加载另一个页面并等待它,只需在此处重复完全相同的代码即可(但请记住要重命名变量!)。

RemoveHandler WebBrowser1.DocumentCompleted,DocumentCompletedHandler’删除事件处理程序(如果您不希望两次调用此事件处理程序)。
如果
结束,则结束

AddHandler WebBrowser1.DocumentCompleted,DocumentCompletedHandler

WebBrowser1.Navigate( https://www.facebook.com/ )

Lambda Expression解决方案的优点是,添加和删除起来都更容易例如,执行网页自动化时需要多个处理程序。






编辑:



如果您要执行自动化,我建议使用Lambda解决方案。这样,您可以根据需要执行的操作,更加动态地添加和删除 DocumentCompleted 事件的处理程序。



要等待具有指定文本的元素出现,可以启动计时器,该计时器将对所有元素进行迭代,并在每次打勾时检查其 InnerText



在下面的示例中,我将计时器的滴答间隔设置为250 ms,因此它将每秒检查一次元素4次。您可以根据需要进行调整,但是请不要使用太小的延迟,因为这会增加CPU使用率。

  Dim WithEvents StepTwoWaitingTimer As带有{.Interval = 250}的新计时器

Private Sub Button1_Click(发送者作为对象,e作为EventArgs)处理Button1.Click
Dim StepOneHandler作为WebBrowserDocumentCompletedEventHandler = _
Sub(wsender作为对象,我们作为WebBrowserDocumentCompletedEventArgs)
如果WebBrowser1.ReadyState = WebBrowserReadyState.Complete然后
StepTwoWaitingTimer.Start()'开始等待所需元素的出现。

RemoveHandler WebBrowser1.DocumentCompleted,StepOneHandler
如果
End Sub

AddHandler WebBrowser1.DocumentCompleted,StepOneHandler

WebBrowser1。 Navigate(此处的URL)
结束子

私有子类StepTwoWaitingTimer_Tick(发送者为对象,e作为EventArgs)处理StepTwoWaitingTimer.Tick
'用 _54nh迭代每个元素类。
用于WebBrowser1.Document.GetElementsByClassName( _ 54nh)中的HtmlElement的每个元素
如果Element.InnerText = TEXTINSIDETHETAG,则找到
’Element。单击它并停止计时器。
Element.InvokeMember( click)
StepTwoWaitingTimer.Stop()

退出’停止循环。
结束,如果
下一个
结束子


This is the situation:

  • I have a webBrowser in a VB .NET project
  • I do a login on Facebook
  • I have to wait for the page / javascript output to finish loading

I want to set a waiting timer in seconds that do not stop the loading of the browser.

This solution seem not to work:

    Do While WebBrowser1.ReadyState <> WebBrowserReadyState.Complete
        Application.DoEvents()
    Loop

解决方案

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

这篇关于如何创建不停止WebBrowser加载的等待计时器?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆