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

时间:2021-05-12 21:08:59

I have a WebBrowser control which is being instantiated dynamically from a background STA thread because the parent thread is a BackgroundWorker and has lots of other things to do.

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

The problem is that the Navigated event never fires, unless I pop a MessageBox.Show() in the method that told it to .Navigate(). I shall explain:

问题是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;
}

This works fine; but the messagebox will get in the way since this is an automation app. When I remove the MessageBox.Show(), the WebBrowser.Navigated event never fires. I've tried supplanting this line with a Thread.Sleep(), and by suspending the parent thread.

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

Once I get this out of the way, I intend to Suspend the parent thread while the WebBrowser is doing its job and find some way of passing the resulting HTML back to the parent thread so it can continue with further logic.

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

Why does it do this? How can I fix it?

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

If someone can provide me with a way to fetch the content of a web page, fill out some data, and return the content of the page on the other side of the submit button, all against a webserver that doesn't support POST verbs nor passing data via QueryString, I'll also accept that answer as this whole exercise will have been unneccessary.

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


Solution: I ended up just not using the BackgroundWorker and slave thread at all at the suggestion of the team architect... Though at the expense of responsiveness :(

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

6 个解决方案

#1


2  

WebBrowser won't do much unless it is shown and has a UI thread associated; are you showing the form on which it resides? You need to, to use the DOM etc. The form could be off-screen if you don't want to display it to the user, but it won't work well in a service (for example).

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

For scraping purposes, you can normally simulate a regular HTML browwser using WebClient etc. IS this not sufficient? You can use tools like "Fiddler" to investigate the exact request you need to make to the server. For more than that, you might look at the HTML Agility Pack, which offers DOM access to HTML without a browser.

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

#2


1  

The Navigated and DocumentComplete events will not fire if the visibility of the WebBrowser is set to false. You can work around this limitation by making the WebBrowser visible but setting it's location so that it is outside of the user interface like:

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

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

#3


1  

you need to add a line that's like this:

你需要添加一行如下:

webBrowser1.Navigated += new WebBrowserNavigatedEventHandler(webBrowser1_Navigated);

where webBrowswer1_Navigated is the function you want called when the event fires.

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

#4


0  

Is there a GUI thread already started? Perhaps the WebBrowser object uses a GUI thread to handle events. In that case, you should call Application.Run() from the thread that creates the WebBrowser (replace your MessageBox.Show() with this). Application.Run() will hang until Application.Exit() is called.

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

Trying to test this now.

试着现在测试一下。

#5


0  

I ended up just not using the BackgroundWorker and slave thread at all at the suggestion of the team architect... Though at the expense of responsiveness :(

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

#6


0  

A WebBrowser control can't work if it is not in a STA Thread. If you want to use a WebBrowser instance in a thread you need to create your thread and call Thread.SetApartmentState(ApartmentState.STA);

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

#1


2  

WebBrowser won't do much unless it is shown and has a UI thread associated; are you showing the form on which it resides? You need to, to use the DOM etc. The form could be off-screen if you don't want to display it to the user, but it won't work well in a service (for example).

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

For scraping purposes, you can normally simulate a regular HTML browwser using WebClient etc. IS this not sufficient? You can use tools like "Fiddler" to investigate the exact request you need to make to the server. For more than that, you might look at the HTML Agility Pack, which offers DOM access to HTML without a browser.

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

#2


1  

The Navigated and DocumentComplete events will not fire if the visibility of the WebBrowser is set to false. You can work around this limitation by making the WebBrowser visible but setting it's location so that it is outside of the user interface like:

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

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

#3


1  

you need to add a line that's like this:

你需要添加一行如下:

webBrowser1.Navigated += new WebBrowserNavigatedEventHandler(webBrowser1_Navigated);

where webBrowswer1_Navigated is the function you want called when the event fires.

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

#4


0  

Is there a GUI thread already started? Perhaps the WebBrowser object uses a GUI thread to handle events. In that case, you should call Application.Run() from the thread that creates the WebBrowser (replace your MessageBox.Show() with this). Application.Run() will hang until Application.Exit() is called.

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

Trying to test this now.

试着现在测试一下。

#5


0  

I ended up just not using the BackgroundWorker and slave thread at all at the suggestion of the team architect... Though at the expense of responsiveness :(

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

#6


0  

A WebBrowser control can't work if it is not in a STA Thread. If you want to use a WebBrowser instance in a thread you need to create your thread and call Thread.SetApartmentState(ApartmentState.STA);

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