【问题标题】:WebBrowser control: "Specified cast is not valid."WebBrowser 控件:“指定的强制转换无效。”
【发布时间】:2011-05-01 13:59:31
【问题描述】:

我使用 WebBrowser 控件导航到 WordPress 博客的登录页面。 该页面加载正常,但每当我尝试从线程访问 WebBrowser 时。我得到一个特定的演员表是无效的例外。同样在调试时,一切都会冻结大约 5 秒。调试时,我尝试访问控件。我的所有成员变量都出现超时错误。

//in constructor of main form
Thread.CurrentThread.ApartmentState = ApartmentState.STA;
this.CheckForIllegalCrossThreadCalls = false;

mainThreadHandle = new Thread(mainThread);
mainThreadHandle.Start();

private void mainThread()
{
    wbMain.Navigate("http://example.com/");

    //navigating is set to false in the document complete event.
    navigating = true;

    while (navigating == true)
        Thread.Sleep(5000);

    try
    {
        //Where I get the issues
        MessageBox.Show(wbMain.DocumentText);
    }
    catch (Exception e)
    {

    }

    Thread.Sleep(1000);
}

【问题讨论】:

  • 你能把Specified cast is not valid异常的代码贴出来吗?
  • 您的代码中有错误。您需要查看您的代码并找到错误。
  • 代码冻结 5 秒,因为您将其发送到睡眠 5000 毫秒。
  • @Shadow Wizard 我说的是冻结,而不是睡眠。我知道区别。每当我尝试访问控件本身时,它都会冻结大约 5 秒钟。我的整个 IDE 冻结了。
  • 如果你移除睡眠,它仍然会冻结吗?

标签: c# .net winforms webbrowser-control


【解决方案1】:

WebBrowser 是一个底层的 COM 组件。一个单元线程,COM 负责以线程安全的方式调用它的方法。由于这个原因,您的 Navigate() 调用有效,它实际上是在 UI 线程上执行的。不起作用的是 DocumentText 属性,它是在 .NET 包装器中实现的,他们在某种程度上弄乱了代码。当 CLR 中的 COM 互操作支持注意到 MTA 中的线程试图访问 STA 上的组件的属性时,它就会爆炸。

您对 SetApartmentState() 的调用不正确。它是在错误的线程上制作的,UI 线程已经是 STA。也是它不爆炸的原因,你不能在线程启动后改变它的单元状态。您必须在您创建的 Thread 对象上调用它。还是没有解决你的问题,两个STA线程不兼容。

解决问题的两种基本方法。第一个是您在单独的 STA 线程上创建 WebBrowser 对象本身。 this answer 中的代码向您展示了如何做到这一点。

您以这种方式创建的浏览器也不会在您的表单上可见。这是第二种方式,使用 Control.Invoke() 自己编组调用。然而,这样做毫无意义,无论如何,您的所有代码都在 UI 线程上执行,您没有并发性。这里没有免费的午餐。在线程上运行它只会让你头疼。如果您需要时间来处理文档文本,请在单独的线程上运行 那个 代码。

【讨论】:

【解决方案2】:

为什么在使用 WebBrowser 控件时不使用事件模型?

NavigatingNavigatedProgressChangedDocumentCompleted

【讨论】:

  • 我是为了获取浏览器的状态,但是对于我正在执行的任务,它需要一个单独的线程来不挂起应用程序。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-21
  • 2018-05-27
  • 2014-07-30
  • 2012-06-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多