public ChromiumFxDispatcher(CfrBrowser browser, CfrV8Context context, IWebSessionLogger logger) { _Logger = logger; _Browser = browser; _Context = context; TaskRunner = _Context.TaskRunner; _CfrTask = new CfrTask(); _CfrTask.Execute += CfrTask_Execute; }
/// <summary> /// Post a task for execution on the specified thread. Equivalent to using /// CfrTaskRunner.GetForThread(threadId).PostTask(task). /// </summary> /// <remarks> /// See also the original CEF documentation in /// <see href="https://bitbucket.org/chromiumfx/chromiumfx/src/tip/cef/include/capi/cef_task_capi.h">cef/include/capi/cef_task_capi.h</see>. /// </remarks> public static bool PostTask(CfxThreadId threadId, CfrTask task) { var call = new CfxRuntimePostTaskRenderProcessCall(); call.threadId = (int)threadId; call.task = CfrObject.Unwrap(task); call.RequestExecution(CfxRemoteCallContext.CurrentContext.connection); return(call.__retval); }
/// <summary> /// Post a task for delayed execution on the specified thread. Equivalent to /// using CfrTaskRunner.GetForThread(threadId).PostDelayedTask(task, /// delay_ms). /// </summary> /// <remarks> /// See also the original CEF documentation in /// <see href="https://bitbucket.org/chromiumfx/chromiumfx/src/tip/cef/include/capi/cef_task_capi.h">cef/include/capi/cef_task_capi.h</see>. /// </remarks> public static bool PostDelayedTask(CfxThreadId threadId, CfrTask task, long delayMs) { var call = new CfxRuntimePostDelayedTaskRenderProcessCall(); call.threadId = (int)threadId; call.task = CfrObject.Unwrap(task); call.delayMs = delayMs; call.RequestExecution(CfxRemoteCallContext.CurrentContext.connection); return call.__retval; }
public ChromiumFxTask(Action perform) { var task = new CfrTask(); task.Execute += (sender, args) => { perform(); Clean?.Invoke(); }; Task = task; }
public ChromiumFxTask(Action perform) { Task = new CfrTask(); Task.Execute += (sender, args) => { perform(); Clean?.Invoke(); Task.Dispose(); Task = null; }; }
private CfrTask AddTask(Action action) { var task = new CfrTask(); task.Execute += (o, e) => { action(); RemoveTask(task); }; lock (_Locker) _Tasks.Add(task); return(task); }
protected void CallCallback(CfrV8Value callback, CfrV8Context v8Context, params KeyValuePair <string, object>[] par) { if (callback != null) { //get render process context var rc = callback.CreateRemoteCallContext(); //enter render process rc.Enter(); //create render task var task = new CfrTask(); task.Execute += (_, taskArgs) => { //enter saved context v8Context.Enter(); var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor()); foreach (var val in par) { var validValue = ConvertValue(val.Value); callbackArgs.SetValue(val.Key, validValue, CfxV8PropertyAttribute.ReadOnly); } //execute callback callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs }); v8Context.Exit(); //lock task from gc lock (task) { Monitor.PulseAll(task); } }; lock (task) { //post task to render process v8Context.TaskRunner.PostTask(task); } rc.Exit(); GC.KeepAlive(task); } }
void CfrTaskStressTest() { if (remoteBrowser == null) { return; } var ctx = remoteBrowser.CreateRemoteCallContext(); ctx.Enter(); try { int taskExecutionCounter = 0; for (int i = 0; i < 10000; ++i) { var task = new CfrTask(); task.Execute += (s, e1) => { ++taskExecutionCounter; if (taskExecutionCounter % 1000 == 0) { LogWriteLine($"CfrTask stress test: {taskExecutionCounter}/10000 tasks executed."); } }; if (i % 2 == 0) { CfrRuntime.PostTask(CfxThreadId.Renderer, task); } else { var tr = CfrTaskRunner.GetForThread(CfxThreadId.Renderer); tr.PostTask(task); } if (i % 1000 == 0) { LogWriteLine($"CfrTask stress test: {i}/10000 tasks posted."); } } } catch { LogWriteLine($"CfrTask stress test: Exception cought, aborting."); } finally { ctx.Exit(); } }
private void AsyncTestFunctionCallback(CfrV8Value function, CfrV8Context v8Context) { LogWriteLine("AsyncTestFunctionCallback: sleep 2 secs, don't browse away..."); Thread.Sleep(2000); var rpcContext = function.CreateRemoteCallContext(); rpcContext.Enter(); // since v8 values can only be accessed from the thread on which they are created, the task // has to be posted for execution on the remote renderer thread (see CfxV8Value summary) var task = new CfrTask(); string result = null; task.Execute += (s, e) => { v8Context.Enter(); LogWriteLine("AsyncTestFunctionCallback -> task.Execute: function.FunctionName = " + function.FunctionName); var args = new CfrV8Value[] { "This is the alert text." }; var retval = function.ExecuteFunction(null, args); result = retval.StringValue; v8Context.Exit(); // release the waiting thread. lock (task) { Monitor.PulseAll(task); } }; // wait until the return value is available. lock (task) { CfrTaskRunner.GetForThread(CfxThreadId.Renderer).PostTask(task); Monitor.Wait(task); } rpcContext.Exit(); LogWriteLine("AsyncTestFunctionCallback: result from callback = " + result); LogWriteLine("AsyncTestFunctionCallback: done."); }
private void RunInContextUnsafe(Action action) { if (CfxRemoteCallContext.IsInContext) { action(); return; } _Actions.Enqueue(action); if (_IsExecutingActions) { return; } using (GetRemoteContext()) { var task = new CfrTask(); task.Execute += CfrTask_Execute; CfrRuntime.PostTask(CfxThreadId.Renderer, task); } }
public Form1() : base("http://res.app.local/www/index.html") { InitializeComponent(); LoadHandler.OnLoadEnd += LoadHandler_OnLoadEnd; //register the "my" object var myObject = GlobalObject.AddObject("my"); //add property "name" to my, you should implemnt the getter/setter of name property by using PropertyGet/PropertySet events. var nameProp = myObject.AddDynamicProperty("name"); nameProp.PropertyGet += (prop, args) => { // getter - if js code "my.name" executes, it'll get the string "NanUI". args.Retval = CfrV8Value.CreateString("NanUI"); args.SetReturnValue(true); }; nameProp.PropertySet += (prop, args) => { // setter's value from js context, here we do nothing, so it will store or igrone by your mind. var value = args.Value; args.SetReturnValue(true); }; //add a function showCSharpMessageBox var showMessageBoxFunc = myObject.AddFunction("showCSharpMessageBox"); showMessageBoxFunc.Execute += (func, args) => { //it will be raised by js code "my.showCSharpMessageBox(`some text`)" executed. //get the first string argument in Arguments, it pass by js function. var stringArgument = args.Arguments.FirstOrDefault(p => p.IsString); if (stringArgument != null) { MessageBox.Show(this, stringArgument.StringValue, "C# Messagebox", MessageBoxButtons.OK, MessageBoxIcon.Information); } }; //add a function getArrayFromCSharp, this function has an argument, it will combind C# string array with js array and return to js context. var friends = new string[] { "Mr.JSON", "Mr.Lee", "Mr.BONG" }; var getArrayFromCSFunc = myObject.AddFunction("getArrayFromCSharp"); getArrayFromCSFunc.Execute += (func, args) => { var jsArray = args.Arguments.FirstOrDefault(p => p.IsArray); if (jsArray == null) { jsArray = CfrV8Value.CreateArray(friends.Length); for (int i = 0; i < friends.Length; i++) { jsArray.SetValue(i, CfrV8Value.CreateString(friends[i])); } } else { var newArray = CfrV8Value.CreateArray(jsArray.ArrayLength + friends.Length); for (int i = 0; i < jsArray.ArrayLength; i++) { newArray.SetValue(i, jsArray.GetValue(i)); } var jsArrayLength = jsArray.ArrayLength; for (int i = 0; i < friends.Length; i++) { newArray.SetValue(i + jsArrayLength, CfrV8Value.CreateString(friends[i])); } jsArray = newArray; } //return the array to js context args.SetReturnValue(jsArray); //in js context, use code "my.getArrayFromCSharp()" will get an array like ["Mr.JSON", "Mr.Lee", "Mr.BONG"] }; //add a function getObjectFromCSharp, this function has no arguments, but it will return a Object to js context. var getObjectFormCSFunc = myObject.AddFunction("getObjectFromCSharp"); getObjectFormCSFunc.Execute += (func, args) => { //create the CfrV8Value object and the accssor of this Object. var jsObjectAccessor = new CfrV8Accessor(); var jsObject = CfrV8Value.CreateObject(jsObjectAccessor); //create a CfrV8Value array var jsArray = CfrV8Value.CreateArray(friends.Length); for (int i = 0; i < friends.Length; i++) { jsArray.SetValue(i, CfrV8Value.CreateString(friends[i])); } jsObject.SetValue("libName", CfrV8Value.CreateString("NanUI"), CfxV8PropertyAttribute.ReadOnly); jsObject.SetValue("friends", jsArray, CfxV8PropertyAttribute.DontDelete); args.SetReturnValue(jsObject); //in js context, use code "my.getObjectFromCSharp()" will get an object like { friends:["Mr.JSON", "Mr.Lee", "Mr.BONG"], libName:"NanUI" } }; //add a function with callback var callbackTestFunc = GlobalObject.AddFunction("callbackTest"); callbackTestFunc.Execute += (func, args) => { var callback = args.Arguments.FirstOrDefault(p => p.IsFunction); if (callback != null) { var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor()); callbackArgs.SetValue("success", CfrV8Value.CreateBool(true), CfxV8PropertyAttribute.ReadOnly); callbackArgs.SetValue("text", CfrV8Value.CreateString("Message from C#"), CfxV8PropertyAttribute.ReadOnly); callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs }); } }; //add a function with async callback var asyncCallbackTestFunc = GlobalObject.AddFunction("asyncCallbackTest"); asyncCallbackTestFunc.Execute += async(func, args) => { //save current context var v8Context = CfrV8Context.GetCurrentContext(); var callback = args.Arguments.FirstOrDefault(p => p.IsFunction); //simulate async methods. await Task.Delay(5000); if (callback != null) { //get render process context var rc = callback.CreateRemoteCallContext(); //enter render process rc.Enter(); //create render task var task = new CfrTask(); task.Execute += (_, taskArgs) => { //enter saved context v8Context.Enter(); //create callback argument var callbackArgs = CfrV8Value.CreateObject(new CfrV8Accessor()); callbackArgs.SetValue("success", CfrV8Value.CreateBool(true), CfxV8PropertyAttribute.ReadOnly); callbackArgs.SetValue("text", CfrV8Value.CreateString("Message from C#"), CfxV8PropertyAttribute.ReadOnly); //execute callback callback.ExecuteFunction(null, new CfrV8Value[] { callbackArgs }); v8Context.Exit(); //lock task from gc lock (task) { Monitor.PulseAll(task); } }; lock (task) { //post task to render process v8Context.TaskRunner.PostTask(task); } rc.Exit(); GC.KeepAlive(task); } }; }
private void RemoveTask(CfrTask task) { task.Dispose(); lock (_Locker) _Tasks.Remove(task); }