WebBrowser控件:“指定的强制转换无效。”

时间:2011-05-01 13:59:32

标签: c# .net winforms webbrowser-control

我使用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);
}

2 个答案:

答案 0 :(得分:8)

WebBrowser是一个引擎盖下的COM组件。一个公寓线程,COM负责以线程安全的方式调用其方法。您的Navigate()调用适用于该原因,它实际上是在UI线程上执行的。什么不起作用的是DocumentText属性,它是在.NET包装器中实现的,它们在某种程度上弄错了代码。当CLR中的COM互操作支持注意到MTA中的线程试图访问存在于STA上的组件的属性时,它会发生炸弹。

您对SetApartmentState()的调用不正确。它是在错误的线程上创建的,UI线程已经是STA。也就是它没有炸弹的原因,你不能在它启动后改变一个线程的公寓状态。您必须在您创建的Thread对象上调用它。它仍然无法解决您的问题,两个STA线程不兼容。

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

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

答案 1 :(得分:1)

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

NavigatingNavigatedProgressChangedDocumentCompleted