【发布时间】:2013-05-18 21:54:30
【问题描述】:
问题范围:
我正在编写一个应用程序来保存从 Bing 和 Google 搜索中检索到的 HTML。我知道有一些类可以使用 this example 等流执行 Web 请求,但由于 Google 和 Bing 都使用 Javascript 和 Ajax 将结果呈现为 HTML,所以我无法简单地读取流并使用 get 到我需要的结果。
解决方案是使用 WebBrowser 类并导航到我想要的 url,以便浏览器本身处理所有 Javascript 和 Ajax 脚本执行。
多线程:
为了提高效率,我有相同的表单应用程序为每个服务触发一个线程(一个用于 Bing,一个用于 Google)。
问题:
因为我需要 WebBrowser,所以我为每个线程(目前是 2 个)实例化了一个。据微软称,有一个known bug that prevents the DocumentCompleted event from firing if the WebBrowser is not visible and is not added to a visible form aswell(更多信息,follow this link)。
真正的问题:
主要问题是浏览器的DocumentCompleted 事件永远不会触发。从不。
我已经为DocumentCompleted 事件编写了一个正确的处理程序,它永远不会得到回调。为了处理浏览器事件触发所需的等待,我实现了一个具有高超时(5 分钟)的AutoResetEvent,如果它在 5 分钟后没有触发我需要的事件,它将处理 webbrowser 线程。
目前,我已创建浏览器并将其添加到 WindowsForm 中,两者都是可见的,但事件仍未触发。
一些代码:
// Creating Browser Instance
browser = new WebBrowser ();
// Setting up Custom Handler to "Document Completed" Event
browser.DocumentCompleted += DocumentCompletedEvent;
// Setting Up Random Form
genericForm = new Form();
genericForm.Width = 200;
genericForm.Height = 200;
genericForm.Controls.Add (browser);
browser.Visible = true;
至于导航,我有以下(浏览器的方法):
public void NavigateTo (string url)
{
CompletedNavigation = false;
if (browser.ReadyState == WebBrowserReadyState.Loading) return;
genericForm.Show (); // Shows the form so that it is visible at the time the browser navigates
browser.Navigate (url);
}
而且,对于导航的调用,我有这个:
// Loading URL
browser.NavigateTo(URL);
// Waiting for Our Event To Fire
if (_event.WaitOne (_timeout))
{
// Success
}
{ // Error / Timeout From the AutoResetEvent }
TL:DR:
我的 WebBrowser 被实例化为另一个 STAThread,添加到表单中,当浏览器导航触发时,两者都可见并显示,但来自浏览器的 DocumentCompleted 事件从未触发,因此 AutoResetEvent 总是超时并且我没有响应来自浏览器。
在此先感谢,很抱歉发了这么长的帖子
【问题讨论】:
-
TL:DR:?这是什么意思?
-
太久没看。
-
这就是你只使用一个 UI 线程的原因。您应该在一个 UI 线程中完成所有这些工作。
-
另请注意,通过阻塞创建浏览器的线程,实际上是在阻止它编组已完成的事件处理程序运行,因为它需要编组到该线程。
-
@MarcelloGrechiLins 您使用一个线程创建两个网络浏览器,告诉它们导航到一个页面,然后处理触发的已完成事件。就像你会做一个,但你使用两个。
标签: c# multithreading browser