2

From the Worker thread I am calling UI thread like:

using(CefGlueBrowserForm cefGlueBrowserForm = new CefGlueBrowserForm(propertyBag.ResponseUri.ToString()))
{
    CefGlueBrowserForm cefGlueBrowserForm = new CefGlueBrowserForm(propertyBag.ResponseUri.ToString());
    cefGlueBrowserForm.Show();

    while (!cefGlueBrowserForm.Done)
    {
        Application.DoEvents();
    }

    propertyBag.GetResponse = () => new MemoryStream(Encoding.UTF8.GetBytes(cefGlueBrowserForm.DocumentDomHtml));
    base.Process(name, propertyBag);
}

and this code is inside thread, but I always get:

System.ComponentModel.InvalidAsynchronousStateException was unhandled
  HResult=-2147024809
  Message=An error occurred invoking the method.  The destination thread no longer exists.
  Source=System.Windows.Forms
  StackTrace:
       at System.Windows.Forms.Control.WaitForWaitHandle(WaitHandle waitHandle)
       at System.Windows.Forms.Control.MarshaledInvoke(Control caller, Delegate method, Object[] args, Boolean synchronous)
       at System.Windows.Forms.Control.Invoke(Delegate method, Object[] args)
       at System.Windows.Forms.Control.Invoke(Delegate method)
       at Xilium.CefGlue.WindowsForms.CefWebBrowser.InvokeIfRequired(Action a)
       at Xilium.CefGlue.WindowsForms.CefWebLoadHandler.OnLoadStart(CefBrowser browser, CefFrame frame)
       at Xilium.CefGlue.CefLoadHandler.on_load_start(cef_load_handler_t* self, cef_browser_t* browser, cef_frame_t* frame)
  InnerException: 

Error is here:

  internal void InvokeIfRequired(Action a)
        {
            if (InvokeRequired)
                Invoke(a); --> ERROR
            else
                a();
        }

It works 2 times (first and second browser) then crash, because first thread close the browser and 2 or 3 browser stop working.

EDIT:

After page in browser is loaded I am calling:

private void OnLoadEnd()
        {
            CefGlueBrowser.LoadEnd += (s, e) =>
                {
                    MyCefStringVisitor visitor = new MyCefStringVisitor(this, m_url);
                    CefGlueBrowser.Browser.GetMainFrame().GetSource(visitor);
                };
        }

How can I solve this? I want to have multithread UI browsers...

senzacionale
  • 20,448
  • 67
  • 204
  • 316

1 Answers1

2

There is really no way to definitively solve this problem because it's a race condition. The background thread cannot guarantee that the foreground thread exists throughout the Invoke process. It could exist when Invoke begins execution but be killed before the callback actually runs. This is just a case you have to handle in the method that calls Invoke

JaredPar
  • 733,204
  • 149
  • 1,241
  • 1,454
  • Thank you. So I need to chnage CefWebBrowser logic? – senzacionale Dec 19 '13 at 15:46
  • @senzacionale yes, you need to change it to not crash essentially when this scenario happens – JaredPar Dec 19 '13 at 15:46
  • Thx. only solution is with try catch as I understand. And I modified my question, i am also calling OnLoadEnd event – senzacionale Dec 19 '13 at 15:48
  • Hi mans. I'm completely agreed, but with addition: CefWebBrowser control are exist are sample only. Feel free to change it as you want. I'm saying it as author of CefGlue. Best practice of most projects when i'm using CefGlue - is develop control like CefWebBrowser for you needs (based on given implementation). There is no exist ultimate way to integrate CEF transparently - so better that you will control browser's lifetime explicitly. This means, that CefWebBrowser must be extended with flag that underlying browser destroyed and suppress any events. – Dmitry Azaraev Dec 19 '13 at 16:48
  • Additionally i'm point to all that InvokeRequired/Invoke technique is bad. Better catch SynchronizationContext. Problem with InvokeRequired that it can lie, usually when control's handle is not created. There are was be lot of issues usually dated around 2003-2006 years. Still now it works same. :) So in general - fix it for self, or propose fix to commit in repository (better via pull request). In conjunction with try/catch around Invoke i can propose only try do not call it, if control is already destroyed. Thanks. – Dmitry Azaraev Dec 19 '13 at 16:50
  • Hi fddima. Thank you for your reply and thx for developing CefGlue. I will create my control as you said but I have one more question. "This means, that CefWebBrowser must be extended with flag that underlying browser destroyed and suppress any events." So how exactly do you mean to extend it? – senzacionale Dec 20 '13 at 11:49