WebBrowser.Navigated仅在MessageBox.Show()时触发

时间:2008-12-15 20:26:59

标签: c# multithreading delegates browser apartments

我有一个WebBrowser控件,它是从后台STA线程动态实例化的,因为父线程是BackgroundWorker,还有很多其他事情要做。

问题是Navigated事件永远不会触发,除非我在告诉它的方法中弹出MessageBox.Show().Navigate()。我将解释:

ThreadStart ts = new ThreadStart(GetLandingPageContent_ChildThread);
Thread t = new Thread(ts);
t.SetApartmentState(ApartmentState.STA);
t.Name = "Mailbox Processor";
t.Start();

protected void GetLandingPageContent_ChildThread()
{
 WebBrowser wb = new WebBrowser();
 wb.Navigated += new WebBrowserNavigatedEventHandler(wb_Navigated);
 wb.Navigate(_url);
 MessageBox.Show("W00t");
}

protected void wb_Navigated(object sender, WebBrowserNavigatedEventArgs e)
{
 WebBrowser wb = (WebBrowser)sender; // Breakpoint
 HtmlDocument hDoc = wb.Document;
}

这很好用;但由于这是一个自动化应用程序,因此消息框将受到阻碍。当我删除MessageBox.Show()时,WebBrowser.Navigated事件永远不会触发。我试过用Thread.Sleep()取代这一行,并暂停父线程。

一旦我解决了这个问题,我打算在WebBrowser正在执行其工作时挂起父线程,并找到将生成的HTML传递回父线程的一些方法,以便它可以继续进一步的逻辑。

为什么这样做?我该如何解决?

如果有人可以为我提供获取网页内容的方法,请填写一些数据,并在提交按钮的另一侧返回页面内容,所有内容都针对不支持的网络服务器POST动词也不通过QueryString传递数据,我也接受这个答案,因为整个练习都是不必要的。


解决方案:根据团队架构师的建议,我最终根本没有使用BackgroundWorker和奴隶线程......虽然以牺牲响应性为代价:(

6 个答案:

答案 0 :(得分:2)

WebBrowser除非显示并且与UI线程关联,否则不会做太多事情;你在显示它所在的表格吗?您需要,使用DOM等。如果您不想将表单显示给用户,表单可能在屏幕外,但它在服务中不能很好地工作(例如)。

出于抓取目的,您通常可以使用WebClient等模拟常规HTML浏览器。这还不够吗?您可以使用“Fiddler”等工具来调查您需要向服务器发出的确切请求。除此之外,您可以查看HTML Agility Pack,它在没有浏览器的情况下提供对HTML的DOM访问。

答案 1 :(得分:1)

如果WebBrowser的可见性设置为false,则不会触发Navigated和DocumentComplete事件。您可以通过使WebBrowser可见但设置它的位置以使其位于用户界面之外来解决此限制,如:

wb.Visible = true;
wb.Left = -wb.Width; // notice the minus sign

答案 2 :(得分:1)

你需要添加一行如下:

webBrowser1.Navigated += new WebBrowserNavigatedEventHandler(webBrowser1_Navigated);

其中webBrowswer1_Navigated是您要在事件触发时调用的函数。

答案 3 :(得分:0)

是否已启动GUI线程?也许WebBrowser对象使用GUI线程来处理事件。在这种情况下,您应该从创建WebBrowser的线程调用Application.Run()(用此替换您的MessageBox.Show())。 Application.Run()将挂起,直到调用Application.Exit()。

现在尝试测试一下。

答案 4 :(得分:0)

根据团队建筑师的建议,我最终根本没有使用BackgroundWorker和奴隶线程......虽然以牺牲响应性为代价:(

答案 5 :(得分:0)

如果WebBrowser控件不在STA线程中,则它无法工作。如果要在线程中使用WebBrowser实例,则需要创建线程并调用Thread.SetApartmentState(ApartmentState.STA);