【问题标题】:How to create a waiting timer that does not stop the loading of a WebBrowser?如何创建一个不停止加载 WebBrowser 的等待计时器?
【发布时间】:2018-01-05 09:16:42
【问题描述】:

情况是这样的:

  • 我在 VB .NET 项目中有一个 webBrowser
  • 我在 Facebook 上登录
  • 我必须等待页面/javascript 输出完成加载

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

这个解决方案似乎不起作用:

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

【问题讨论】:

    标签: .net vb.net webbrowser-control


    【解决方案1】:

    您应该永远不要使用 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
    

    【讨论】:

    • 谢谢,这个方法不错,但是当页面用javascript修改自己的时候就不行了,我真的需要一个定时器控制的动作
    • @MasterKongling :在这些情况下从未考虑过Javascript,不。您是在等待特定元素的出现还是只是一个脚本?
    • 我可以在加载页面后使用您的方法进行单击,但是当 facebook 加载可能使用 ajax 的选择时,我无法获得它的 outerHTML...我需要等待...可能
    • @MasterKongling :在这种情况下最好使用Timer 来不断检查元素或其内容是否存在,是的。如果您回答以下问题,我可以更新我的帖子:select 元素的 ID 是什么?您打算用它做什么?
    • 好的,谢谢没有id,我只知道标签里面的文字:TEXTINSIDETHETAG动作是点击,
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-31
    • 2021-09-21
    • 1970-01-01
    • 2019-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多