【发布时间】:2013-05-25 04:05:47
【问题描述】:
是否可以/推荐将后台工作线程与 Web 浏览器控件一起使用?
我正在创建一个机器人,它在 google 中搜索关键字,然后检查前 10 个页面中的网站以查看网站是否排名。
用户最多可以提供 20 个站点进行检查,并且可以使用代理。所以理想情况下,我希望有 5 个线程同时工作。
有可能吗?我可能在某处听说 WebBrowser 控件和线程存在问题。
【问题讨论】:
标签: c#
是否可以/推荐将后台工作线程与 Web 浏览器控件一起使用?
我正在创建一个机器人,它在 google 中搜索关键字,然后检查前 10 个页面中的网站以查看网站是否排名。
用户最多可以提供 20 个站点进行检查,并且可以使用代理。所以理想情况下,我希望有 5 个线程同时工作。
有可能吗?我可能在某处听说 WebBrowser 控件和线程存在问题。
【问题讨论】:
标签: c#
事实并非如此。 WebBrowser 使用 Internet Explorer,它是一个 COM 组件。 COM 组件有一个线程模型,IE 使用“Apartment”。这是一个昂贵的词,意味着它不是线程安全的。您可以在 BGW 中调用其方法,但 COM 会自动将调用编组到 UI 线程。由于所有方法调用和属性访问实际上都发生在 UI 线程上,因此您将通过使用 BGW 使其变慢。
您实际上可以在另一个线程上运行 WebBrowser,您必须在该线程上创建它的一个实例。你必须创建一个线程,即所谓的单线程单元。 STA,您可能从 Winforms 或 WPF 应用程序的 Main() 方法的 [STAThread] 属性中识别出的首字母缩写词。将工作线程更改为 STA 需要在启动之前调用 Thread.SetApartmentState()。您不能对 BGW 执行此操作。并且线程必须泵送一个消息循环来实现 STA 合约,它必须调用 Application.Run()。一方面,需要让 WebBrowser 引发其事件。 This answer 展示了方法。
考虑使用 WebRequest 类。
【讨论】:
WebBrowser.Navigate() not 时遇到了这个答案。我从您的问题中了解到,是的,这是可能的,但没关系,因为所有此类调用都被编组到 UI 线程。我理解正确吗?
您是否有任何理由使用 IE 控制库,例如 HTML Agility pack?它支持多线程,没有 IE 的 COM 噩梦,并且在 HTML 解析方面更强大。
【讨论】:
回答您的直接问题:我从未尝试过,但如果有问题,我不会感到惊讶。 WinForms 控件通常不打算从主 UI 线程以外的线程访问。您应该使用Control.Invoke() 方法从其他线程运行调用方法。这会将它们排在主 UI 线程上。
要解决更广泛的问题:如果您不需要实际呈现 HTML 以供用户查看,则最好不要使用 WebBrowser 控件。您可以使用HttpWebRequest 类下载页面,该类要轻得多。 WebBrowser 基本上是嵌入在您的应用程序中的成熟的 Internet Explorer。
【讨论】: