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);

 

 

ExpandedBlockStart.gif 代码
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)方法,如下:

 

 

ExpandedBlockStart.gif 代码
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

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

最终代码如下

 

ExpandedBlockStart.gif 代码
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

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

 

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

转载于:https://www.cnblogs.com/xjfhnsd/archive/2010/03/14/1685441.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值