我有一个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和奴隶线程......虽然以牺牲响应性为代价:(
答案 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);