将Webbrowser与Control.invoke一起使用

时间:2011-03-28 20:12:34

标签: c# browser backgroundworker invoke

我正在开发一个用于网页抓取的Windows应用程序。为此,我使用Webbrowser控件 - 我不能使用webrequest / webclient / webresponse类,因为网页是使用javascript动态加载的。
该应用程序工作正常,但由于我做了很多处理,它不必要地加载UI。我间歇性地收到“没有回复”的消息。所以我做的是:

1.在UI线程上创建webbrowser
2.将长时间运行的进程放在后台线程上 3.每当我需要获取页面文档时,我都使用Control.Invoke。
4.通过调用调用将页面文档返回到后台线程

在回调函数中,我可以看到页面的文档被提取得很好。但是,未正确评估返回给后台工作程序的文档(HtmlDocument)。当我单步执行调试器时,我得到“功能评估超时消息...”。我已经使用了语法并继续获得无效的强制转换异常或跨线程消息传递异常。
下面是我编写回调/委托的方式:

private delegate HtmlDocument RefreshDelegate(); 
private HtmlDocument RefreshBrowser()
    {
        WebBrowser br1 = ((WebBrowser)this.Controls["br1"]); //get webbrowser, "br1"
        br1.Refresh(); //refresh browser
        return br1.Document; //is retrieved correctly
   }


现在为后台工作程序中处理“返回”HTMLDocument的代码:

WebBrowser br1 = ((WebBrowser)this.Controls["br1"]); //get the browser
HtmlDocument document = (HtmlDocument)br1.Invoke(new RefreshDelegate(this.RefreshBrowser));  //not evaluated 
//do stuff with document


遇到调试器消息:“功能评估已禁用,因为先前的功能评估已超时。您必须继续执行以重新启用功能评估。”。这是解决这个问题的正确方法吗?正如我所说,我无法使用webrequest等获取javascript内容,我也无法在UI上运行htmldocument解析,因为它会导致糟糕的用户体验。另外,我需要创建几个webbrowser实例。如果这不是最好的方式,我也会对其他图书馆开放。感谢。

2 个答案:

答案 0 :(得分:2)

这是因为您在工作线程或调试器线程中调用的WebBrowser方法实际上并未在该线程上运行。 WebBrowser是一个公寓线程COM组件,COM自动编组从工作者回调到UI线程的调用。这在调试器中不能很好地工作,因为调试器冻结了UI线程。

你无法做到这一点,实际上在UI线程上运行这些调用仍然会让你对UI冻结开放。解决这个问题的唯一办法是在自己的STA线程上完全关闭浏览器。你不能看它,不应该是我想象的问题。检查this answer以获取您需要的代码。

答案 1 :(得分:1)

我建议使用HtmlAgilityPack。这是专门为网络“刮”而设计的。

http://htmlagilitypack.codeplex.com/