• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
张纯睿
博客园    首页    新随笔    联系   管理    订阅  订阅

WebBrowser和多线程

http://www.189works.com/article-43518-1.html

 

我们在做采集软件的时候

有些网站通过直接分析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

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

posted @ 2012-09-05 14:10  张纯睿  阅读(347)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3