Javascript To Native Code Async Callback - Blocking??

Having problems with building or using the CefGlue .NET/Mono binding? Ask your questions here.

Moderator: fddima

Javascript To Native Code Async Callback - Blocking??

Postby SimonKay » Thu Nov 07, 2013 1:09 pm

I'm attempting to implement a async callback from javascript into my code. I'm using CefV8Handler CefTask to attempt to do this.

CefV8Handler Execute Method:
Code: Select all
 protected override bool Execute(string name, CefV8Value obj, CefV8Value[] arguments, out CefV8Value returnValue, out string exception)
        {
            if (name == "updateCIP")
            {
                returnValue = CefV8Value.CreateNull();
                exception = null;
                if (arguments.Length == 1 && arguments[0].IsFunction)
                {
                    var trunner = CefTaskRunner.GetForCurrentThread();
                    trunner.PostTask(new CipUpdateTask(CefV8Context.GetCurrentContext(),arguments[0]));
                    return true;
           }
           else

           {
               returnValue = CefV8Value.CreateNull();
               exception = "Function Not Found!";
           }
           
            return true;
    }


The CipUpdateTask is as follows:
Code: Select all
 internal class CipUpdateTask : CefTask
    {

        CefV8Value cb;
        CefV8Context cbcontext;
        internal CipUpdateTask(CefV8Context context, CefV8Value callback)
        {
            cb = callback;
            cbcontext = context;
        }
        protected override void Execute()
        {
            CefV8Value[] args = new CefV8Value[1];

            var result = signal.WaitOne(10000); ? "Signalled!" : "timeout";
            args[0] = CefV8Value.CreateString(result);
            cbcontext.Enter();
            cb.ExecuteFunction(null, args);
            cbcontext.Exit();
        }
       
    }


I had assumed that the fact i had the signal.WaitOne() in a Tasks Execute would mean that the CefBrowser would remain responsive during this call. However it simply seems to lock and the web application becomes unresponsive until the callback is fired. I need to use this long poll method to immediately update the web browser specific condition. I appreciate I could lower the timeout but this not ideal and I'm not sure why this isn't working as I'd expect without blocking.

Help really appreciated!
SimonKay
Newbie
 
Posts: 3
Joined: Thu Nov 07, 2013 12:56 pm

Re: Javascript To Native Code Async Callback - Blocking??

Postby SimonKay » Fri Nov 08, 2013 5:52 am

OK I think I MAY have cracked it...
the CefTask and TaskRunner classes don't actually seem to create threads as such, more specifically they allow code injection INTO the Cef threading model. Therefore to perform an async task you need to use your own threads.

Thats fine except you can't create a returnable parameter outside of the core Cef threads. So the heavy lifting needs to be done inside a user thread which then executed a CefTask within a CefTaskRunner to perform the argument conversion and actually execute the callback as follows;

V8Handler Execute method:
Code: Select all

        protected override bool Execute(string name, CefV8Value obj, CefV8Value[] arguments, out CefV8Value returnValue, out string exception)
        {
            if (name == "updateCIP")
            {
                returnValue = CefV8Value.CreateNull();
                exception = null;
                if (arguments.Length == 1 && arguments[0].IsFunction)
                {
                    var context =  CefV8Context.GetCurrentContext();
                    var trunner = CefTaskRunner.GetForCurrentThread();
                    new Task(() =>
                    {
                        var result =  signal.WaitOne(10000); ? "my argement retrieved here" : "timeout";
                        trunner.PostTask(
                            new CipCallbackTask(context, arguments[0], new object[] { result }));

                    }).Start();
                    return true;
                }
           }
   else
           {
               returnValue = CefV8Value.CreateNull();
               exception = "Function Not Supported";
           }
           
            return true;
    }


And then my now far simpler CefTask implementation:
Code: Select all
 internal class CipCallbackTask : CefTask
    {
        CefV8Value cb;
        CefV8Context cbcontext;
        string[] argumentsForCallBack;
       
        protected override void Execute()
        {
            CefV8Value[] cbargs = new CefV8Value[argumentsForCallBack.Length];
            for (var i =0;  i < argumentsForCallBack.Length ;i++)
            {
                cbargs[i] = CefV8Value.CreateString(argumentsForCallBack[i]);
            }
            cb.ExecuteFunctionWithContext(cbcontext, null, cbargs);
           
        }
        internal CipCallbackTask(CefV8Context context, CefV8Value callback, string[] args)
        {
            cb = callback;
            cbcontext = context;
            argumentsForCallBack = args;
        }
    }


It's pretty self explanatory I hope but this way my CefV8Values are only created within the correct runner context when needed and my own task can remain responsible for the actual task itself. My only concern is whether I've missed anything that could cause problems, for instance should the context be disposed, i'm unsure how to handle this at this time.
SimonKay
Newbie
 
Posts: 3
Joined: Thu Nov 07, 2013 12:56 pm

Re: Javascript To Native Code Async Callback - Blocking??

Postby hans » Wed Aug 13, 2014 3:56 pm

This is brilliant! I have been looking for this for a while now - solves my issues with structured and Asynchronous JS to Native comms. Nice work!
hans
Newbie
 
Posts: 1
Joined: Wed Aug 13, 2014 3:54 pm


Return to CefGlue Forum

Who is online

Users browsing this forum: No registered users and 15 guests