zoukankan      html  css  js  c++  java
  • 谨慎注意WebBrowser控件的DocumentCompleted事件

     

    引言

    WebBrowser控件的DocumentCompleted事件一般就被认定为是在页面完全加载完毕后产生,而注释中也是这么写的:

    但事实却并非如此。

    首先它不一定会在完全加载完毕时才触发,有时就会在加载过程中就会触发。

    其次按照“完全加载完毕后”来理解,会认为通常一次页面跳转只会引发一次该事件,事实也并非如此,某些页面加载时会引发十多次乃至更多。

    试验

    做一个简单试验,首先设计这样的界面:

    然后为那个转到按钮添加单击事件处理:

    private void button1_Click(object sender, EventArgs e)

    {

        webBrowser1.Navigate(textBox1.Text);

    }

    再为WebBrowser控件的DocumentCompleted事件添加处理:

    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

    {

        listBox1.Items.Insert(0, webBrowser1.ReadyState);

    }

    在这里就是输出WebBrowser控件的ReadyState属性到列表中。

    运行并测试:

    可以看到加载某些页面时会引发很多次该事件,并且状态都是一连串的Interactive。

    究其原因是与页面复杂度有关的,猜想是因iFrame或Ajax加载完毕而触发的。

    而触发DocumentCompleted事件时ReadyState为Complete的情况通常只在每次加载页面时出现一次,所以这时我们才应认为其已完全加载。但也并非一个页面100%只会出现一次这种情况,比如页面中Google的“更多”链接点击后仅仅是弹出一个列表,但这时又会出现一次Complete。

    这会导致什么问题?

    假如在ReadyState为Interactive甚至是Loading时对页面实施操控,那很可能无效或引发异常。

    而假如忽视这种一页多发事件的情况,会导致大量重复操作,从而引发异常或逻辑问题。

    该如何解决?

    以下代码可以确保你不会在未加载完毕时执行操作:

    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

    {

        if (webBrowser1.ReadyState < WebBrowserReadyState.Complete) return;

        //执行正常流程代码…………

    }

    如果需要严格控制每页只能执行一次代码,那么需要附加一个属性或变量来记录上次访问的网址,并据此进行判断:

    private void webBrowser1_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)

    {

        if (webBrowser1.ReadyState < WebBrowserReadyState.Complete || webBrowser1.Url.ToString() == LastUrl) return;

        LastUrl = webBrowser1.Url.ToString();

        //执行正常流程代码…………

    }

     

    public string LastUrl

    {

        get

        {

            return _LastUrl;

        }

        set

        {

            _LastUrl = value;

        }

    }

    private string _LastUrl;

    结语

    WebBrowser是非常实用的控件,但也可说是粗制滥造的典范,各种问题层出不穷,从注释对不上实际功能这一点来看,就知道开发者多么漫不经心了。还有就是ReadyState属性其实是一个非常关键的属性,而开发者却没有设置一个事件来监控其状态变更,真是太失败了。

  • 相关阅读:
    java实验报告三
    学术论文撰写准备事项整理
    mac终端下运行shell脚本
    关于1*1卷积核的理解
    车牌识别项目的准备思路
    快捷键备忘
    跑caffe过程中的备忘
    caffe中全卷积层和全连接层训练参数如何确定
    从零开始足球战术分析
    卷积与反卷积以及步长stride
  • 原文地址:https://www.cnblogs.com/soundcode/p/9282885.html
Copyright © 2011-2022 走看看