Search code examples
c#multithreadinggeckofx

How to Invoke or BeginInvoke Control from another thread


from the class I am calling thread with

using (GeckoBrowserForm geckoBrowserForm = new GeckoBrowserForm(XulRunnerPath, propertyBag.ResponseUri.ToString()))
{
    geckoBrowserForm.show();
}

that execute UI form OnLoad(EventArgs e)

protected override void OnLoad(EventArgs e)
{
    GeckoWebBrowser m_GeckoWebBrowser = new GeckoWebBrowser();
    m_GeckoWebBrowser.Invoke(new Action(() => {
                m_GeckoWebBrowser.Parent = this;
                m_GeckoWebBrowser.Dock = DockStyle.Fill;
                m_GeckoWebBrowser.DocumentCompleted += (s, ee) =>
                {    
                    GeckoHtmlElement element = null;
                    var geckoDomElement = m_GeckoWebBrowser.Document.DocumentElement;
                    if (geckoDomElement != null && geckoDomElement is GeckoHtmlElement)
                    {
                        element = (GeckoHtmlElement)geckoDomElement;
                        DocumentDomHtml = element.InnerHtml;
                    }



      if (m_Url.Equals(m_GeckoWebBrowser.Document.Url.ToString(), StringComparison.OrdinalIgnoreCase))
                    {
                        Done = true;
                        //m_GeckoWebBrowser.Navigate("about:blank");
                        //m_GeckoWebBrowser.Document.Cookie = "";
                        //m_GeckoWebBrowser.Stop();
                    }
                };

                m_GeckoWebBrowser.Navigate(m_Url);
            }));
}

but problem is that code inside Invoke is never executed. Why? How can i execute code inside invoke?

Problem is that GeckoBrowser is a Windows Forms Control. A Control's properties and methods may be called only from the thread on which the Control was created. To do anything with a Control from another thread, you need to use the Invoke or BeginInvoke method, e.g. but how?


Solution

  • OnLoad is called on the UI-thread, therefore invoking is not necessary. Besides that, you could also call these initialization steps in the constructor of the class.

    Update: To create it with a SynchronizationContext:

    void ThreadFunc(object args)
    {
        ...
        var syncContext = (SynchronizationContext) args;
        syncContext.Send(new SendOrPostCallback(_ => {
            using (GeckoBrowserForm geckoBrowserForm = new GeckoBrowserForm(XulRunnerPath, propertyBag.ResponseUri.ToString()))
            {
                geckoBrowserForm.ShowDialog();
            }),
            null);
        ...
    }