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

3

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

你能否发布出现“指定的转换无效”异常的代码? - Bala R
你的代码有一个错误。你需要查看你的代码并找到这个错误。 - SLaks
1
代码冻结了5秒,因为你将其休眠了5000毫秒。 - Shadow The Spring Wizard
@Shadow Wizard 我说的是冻结,不是睡眠。我知道它们之间的区别。每当我尝试访问控件本身时,它会冻结大约5秒钟。我的整个IDE都会冻结。 - Drake
1
如果你移除Sleep,它还会冻结吗? - Shadow The Spring Wizard
你解决了吗?我遇到了类似的问题 - http://stackoverflow.com/questions/22820382/how-to-update-documenttext-with-another-documenttext - LCJ
2个回答

9

WebBrowser是一个COM组件。它是一个单线程的组件,COM会以线程安全的方式调用它的方法。您的Navigate()调用之所以起作用,就是因为它实际上是在UI线程上执行的。不起作用的是DocumentText属性,它是在.NET包装器中实现的,他们在代码方面有些失误。当CLR中的COM互操作支持注意到MTA中的线程尝试访问驻留在STA上的组件的属性时,它会出错。

您对SetApartmentState()的调用不正确。它是在错误的线程上进行的,UI线程已经是STA了。此外,它不会出错,因为在启动线程后无法更改线程的公寓状态。您必须在创建的Thread对象上调用它。它仍然无法解决您的问题,两个STA线程不兼容。

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

以这种方式创建的浏览器不能在您的窗体上可见。第二种方法是使用Control.Invoke()自己进行调用。然而,这样做是相当无意义的,因为您的所有代码都在UI线程上执行,您得不到并发性。这里没有免费的午餐。将其运行在线程上只会给您带来麻烦。如果您需要处理文档文本的时间,请在单独的线程上运行代码。


谢谢提供信息。我有一个相关的问题,作为这个问题的扩展http://stackoverflow.com/questions/22820382/how-to-update-documenttext-with-another-documenttext - LCJ

1

我需要获取浏览器的状态,但是为了完成这个任务,需要一个单独的线程来避免应用程序挂起。 - Drake

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接