是否可以/建议在Web浏览器控件中使用后台工作线程?
我正在创建一个搜索谷歌搜索关键字的机器人,然后检查前10页中的网站,看看网站是否排名。
用户最多可以提供20个站点进行检查,并且可以使用代理。理想情况下,我希望一次有5个线程工作。
有可能吗?我可能听说过WebBrowser控件和线程存在问题。
答案 0 :(得分:15)
不是。 WebBrowser使用Internet Explorer,它是一个COM组件。 COM组件具有线程模型,IE使用“公寓”。这是一个昂贵的词,这意味着它不是线程安全的。您可以在BGW中调用其方法,但COM将自动封送对UI线程的调用。由于所有方法调用和属性访问实际上都发生在UI线程上,因此使用BGW会使更慢。
实际上,您可以在另一个线程上运行WebBrowser,您必须在该线程上创建它的实例。而且你必须创建一个所谓的单线程公寓的线程。 STA,您可能从Winforms或WPF应用程序的Main()方法的[STAThread]属性中识别出的首字母缩写词。将工作线程更改为STA需要在启动之前调用Thread.SetApartmentState()。你不能为BGW做这件事。并且线程必须通过消息循环来实现STA合同,它必须调用Application.Run()。例如,要求WebBrowser引发其事件。 This answer显示了这种方法。
考虑使用WebRequest类。
答案 1 :(得分:1)
您是否有任何理由对HTML Agility pack等库使用IE控件?这支持多线程而没有IE的COM噩梦,而且HTML解析功能更强大。
答案 2 :(得分:1)
回答你的直接问题:我从来没有尝试过,但如果遇到问题我也不会感到惊讶。通常,WinForms控件不能从主UI线程以外的线程访问。您应该使用Control.Invoke()
方法从其他线程运行调用方法。这会将它们排到主UI线程上。
要解决更广泛的问题:如果您不需要实际呈现HTML以供用户查看,那么您最好不要使用WebBrowser控件。您可以使用HttpWebRequest
类下载页面,该类更轻松。 WebBrowser基本上是嵌入在应用程序中的完整Internet Explorer。