BackgroundWorker和WebBrowser控件

是否可以/建议在Web浏览器控件中使用后台工作线程?

我正在创建一个搜索谷歌搜索关键字的机器人,然后检查前10页中的网站,看看网站是否排名。

用户最多可以提供20个站点进行检查,并且可以使用代理。 理想情况下,我希望一次有5个线程工作。

可能吗? 我可能听说过WebBrowser控件和线程存在问题。

它不是。 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引发其事件。 这个答案显示了这种方法。

考虑使用WebRequest类。

您是否有任何理由在HTML Agility Pack等库中使用IE控件? 这支持multithreading而没有IE的COM噩梦,而且HTML解析function更强大。

回答你的直接问题:我从未尝试过,但如果遇到问题我也不会感到惊讶。 通常,WinForms控件不能从主UI线程以外的线程访问。 您应该使用Control.Invoke()方法从其他线程运行调用方法。 这会将它们排到主UI线程上。

要解决更广泛的问题:如果您不需要实际呈现HTML以供用户查看,那么您最好不要使用WebBrowser控件。 您可以使用HttpWebRequest类下载页面,该类更轻松。 WebBrowser基本上是嵌入在您的应用程序中的完整Internet Explorer。