• WebBrowser多线程带来的麻烦


    我们在做采集软件的时候

    有些网站通过直接分析html文本是很麻烦的事情

    在利用WinForm编程的情况下

    有一种更好的方式当然是分析HtmlDocument

    然而,这HtmlDoucment并不能直接创建

    它必须由 WebBroswer控件Navigate生成一个页面后

    才能取得wb.HtmlDocument

    然后就可以对HtmlDocument的各元素、标签进行分析。

    事实上,在采集的时候

    并不是采集只会采集单个页面

    这样的话,在主窗体中就可以完成

    譬如采集一些列表页面,有N多个页

    那么,一个循环下去,

    用WebBrowser去响应,那就会导致假死

    这时候,我们肯定会想到用多线程去做这件事情

    C#的多线程,

    大家应该都知道,有STA,MTA两种模式

    然而,WebBrowser控件却有一个不好的特点

    那就是:它只支持多线程STA模式

    例如下面的代码,

    Thread tread = new Thread(new ParameterizedThreadStart(BeginCatch));
    tread.SetApartmentState(ApartmentState.STA);
    tread.Start(url);
    代码
    private void BeginCatch(object obj)
    {
         
    string url = obj.ToString();
         WebBrowser wb 
    = new WebBrowser();
         wb.ScriptErrorsSuppressed 
    = true;
         wb.Navigate(url);
         wb.DocumentCompleted 
    += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);

    需要分析WebBrowser产生 的HtmlDocument时,必须在事件DocumentCompleted里面去操作

    只有这时候,WebBrowser才算加载完成

    不过,这只是一个陷阱!!!!

    WebBrowser有一个特性,那就是在多线程STA的时候,根本就不等到DocumentCompleted的执行

    也就是无法再进行后面的操作!!!

    这样的话,我们该如何办呢?

    也许有人会想:wb.Document.Write(string)方法,如下:

    代码
    private void BeginCatch(object obj)
    {
         
    string url = obj.ToString();
         WebBrowser wb 
    = new WebBrowser();
         wb.ScriptErrorsSuppressed 
    = true;
         string htmlcode = GetHtmlSource(url); 
         wb.Document.Write(htmlcode);
         //执行分析操作    

    //WebClient取网页源码
    private string GetHtmlSource(string Url)
    {
        
    string text1 = "";
         
    try
         {
            System.Net.WebClient wc 
    = new WebClient();
            text1 
    = wc.DownloadString(Url);
         }
        
    catch (Exception exception1)
         {}
        
    return text1;
    }

    但这时候,我们会发现,wb.DocumentText总是没有的

    当时我也很郁闷,搜索园子里的文章与MSDN,都是可以用DocumentText赋值的

    但也在网上发现了很多说操作后没有结果的

    经过努力搜索

    在园子里发现了一篇有用的文章里提到的一个例子

    经过测试后发现

    WebBrowser必须经过Navigate后才会产生Document

    于是忽,终于可以实现了多线程下面的操作了

    最终代码如下

    代码
    private void ThreadWebBrowser(string url)
    {
       Thread tread 
    = new Thread(new ParameterizedThreadStart(BeginCatch));
       tread.SetApartmentState(ApartmentState.STA);
       tread.Start(url);
    }

    private void BeginCatch(object obj)
    {
         
    string url = obj.ToString();
         WebBrowser wb 
    = new WebBrowser();
         wb.ScriptErrorsSuppressed 
    = true;
         
    //在这里Navigate一个空白页面
         wb.Navigate("about:blank");
         
    string htmlcode = GetHtmlSource(url); 
         wb.Document.Write(htmlcode);
         
    //执行分析操作   ……(略) 

    //WebClient取网页源码
    private string GetHtmlSource(string Url)
    {
         
    string text1 = "";
         
    try
         {
            System.Net.WebClient wc 
    = new WebClient();
            text1 
    = wc.DownloadString(Url);
         }
         
    catch (Exception exception1)
         {}
         
    return text1;
    }

    当然,在线程里面处理每个结点与数据库操作的时候,可以用ThreadPool

    这样效果与性能可能好一些

    希望此文对有大家有所帮助~:)

  • 相关阅读:
    debian 中安装GIT
    多核处理器 利用多线程 加速 编译内核 速度
    ubuntu下安装中文输入法(乱码等问题)
    ubuntu 10.04源 更新源列表
    php empty,isset,is_null比较(差异与异同) Leone
    Win 7 各版本的含义 Leone
    Atitit DbServiceV4qb9 数据库查询类库v4 新特性
    Atitit 图像处理之仿油画效果 Oilpaint油画滤镜 水彩画 漫画滤镜 v2
    Atitit 多继承实现解决方案 java c#
    Atitit 基于图片图像 与文档混合文件夹的分类
  • 原文地址:https://www.cnblogs.com/xjfhnsd/p/1685441.html
Copyright © 2020-2023  润新知