在多线程应用程序中使用GeckoFX

时间:2011-03-30 17:55:13

标签: .net geckofx

我在掌握使用GeckoFX时如何处理线程时遇到问题 - 在其他线程中尝试使用GeckoWebBrowser时,它似乎不断抛出错误。

具体而言,我在此测试应用程序中尝试做的是生成网页的缩略图并将其显示在表单上(而不是WebBrowser控件本身)。在单线程工作时,效果很好:

private void browser_DocumentCompleted(object sender, EventArgs e)
{
    GeckoWebBrowser browser = sender as GeckoWebBrowser;
    if (browser.Url.ToString() != "about:blank")
    {
        webBrowserReady = true;
    }
}

private void btnGo_Click(object sender, EventArgs e)
{
    Xpcom.Initialize();

    GeckoWebBrowser browser = new GeckoWebBrowser();
    browser.Width = 1600;
    browser.Height = 1200;
    browser.DocumentCompleted += new EventHandler(browser_DocumentCompleted);
    webBrowserReady = false;        
    browser.CreateControl();
    browser.Navigate(txtUrl.Text);

    while (!webBrowserReady)
        Application.DoEvents();

    if (webBrowserReady)
        DrawWebBrowserToImage(browser);

    browser.Dispose();
}

但是,如果我将浏览器创建和渲染移动到自己的线程中,当我尝试调用CreateControl()时出现COM错误:

Xpcom.Initialize();
Thread t = new Thread(new ThreadStart(()=>{
    GeckoWebBrowser browser = new GeckoWebBrowser();
    /* all the rest of the gecko stuff here too */
}
t.Start();

要解决这个问题,我可以将Xpcom.Initialize调用移动到线程中:

Thread t = new Thread(new ThreadStart(()=>{
    Xpcom.Initialize();
    GeckoWebBrowser browser = new GeckoWebBrowser();
    /* all the rest of the gecko stuff here too */
}
t.Start();

这很好......一次。我第二次尝试导航时,DocumentCompleted只会被触发一次(大约是:空白)。一段时间后,也会弹出COM错误。这似乎向我表明,调用Xpcom.Initialize(一个静态方法,每个应用程序只能调用一次,并且后续每次都不执行任何操作)永久地将GeckoFX绑定到该特定线程。永远。

有没有办法让Xpcom和GeckoFX在多线程环境中正常工作?

2 个答案:

答案 0 :(得分:0)

这将解决您的问题,将其放在导航请求的末尾:

myGeckoFxBrowser.Navigate("about:blank");
myGeckoFxBrowser.Document.Cookie = "";
myGeckoFxBrowser.Stop();

答案 1 :(得分:0)

GeckoFx can only be called from the same thread on which it was initialized (normally the UI thread)

所以如果你想调用GeckoFx Control,那么该方法必须来自初始化GeckoFx控件的线程,通常是你的UI线程,就像你的情况一样。 您可以在BeginInvoke课程中使用Form,请尝试以下操作:

        this.BeginInvoke(new Action(() =>
        {
           browser.Navigate(txtUrl.Text);
            //your code
        }));