【问题标题】:WebBrowser.Navigated Only Fires when I MessageBox.Show();WebBrowser.Navigated 仅在我 MessageBox.Show() 时触发;
【发布时间】:2010-09-27 01:02:17
【问题描述】:

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

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

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 和从属线程......虽然以牺牲响应能力为代价:(

【问题讨论】:

    标签: c# multithreading delegates browser apartments


    【解决方案1】:

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

    【讨论】:

      【解决方案2】:

      你需要添加这样一行:

      webBrowser1.Navigated += new WebBrowserNavigatedEventHandler(webBrowser1_Navigated);
      

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

      【讨论】:

        【解决方案3】:

        在团队架构师的建议下,我最终根本没有使用 BackgroundWorker 和从属线程......虽然以牺牲响应性为代价:(

        【讨论】:

          【解决方案4】:

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

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

          【讨论】:

          【解决方案5】:

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

          现在正在尝试测试。

          【讨论】:

          • 该应用程序确实有一个带有自己线程的 GUI...您是在谈论创建第二个 GUI 线程吗?这与我在这里创建常规线程有何不同?添加 Application.Run() 使其不会触发,无论是否带有 msgbox。
          • 我想我可以在屏幕外放置一个静态的 WebBrowser(即坐标为 -500、-500 左右)并通过代表调用它......虽然这很痛苦 :)
          【解决方案6】:

          WebBrowser 不会做太多事情,除非它被显示并且关联了一个 UI 线程;您是否正在显示它所在的表格?您需要使用 DOM 等。如果您不想将其显示给用户,该表单可能会在屏幕外显示,但它在服务中无法正常工作(例如)。

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

          【讨论】:

          • 否; WebClient 和 HTTP POST 方法都失败了,因为服务器不支持 HTTP 405。给定有效负载时,WebClient 也无法通过 GET 工作。
          • 嗯,网络浏览器必须以某种方式发送它。通过 fiddler 查看实际的 http 请求,并以此为起点。
          • Marc - 我认为这是一个事件问题,请求的内容并不真正相关。
          • 此控件在服务中运行良好。我做过一件非常相似的事情。您只需要使 GUI 线程变得笨拙。有时也需要调用“CreateHandle()”。
          • 父线程(后台工作者)上的 CreateHandle() 导致“未知软件错误”并且 VS 崩溃。 WebBrowser 没有 Createhandle(),但它有一个 CreateControl(),据说它会强制创建一个句柄。那什么也没做。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-09-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多