// X:\jsc.svn\core\ScriptCoreLib\ActionScript\BCLImplementation\System\Threading\Tasks\Task\Task.Delay.cs //02000022 TestTaskDelay.ApplicationControl+<button3_Click>d__2+<MoveNext>0600001a //arg[0] is typeof System.Boolean //script: error JSC1000: No implementation found for this native method, please implement [System.Threading.Tasks.Task.ConfigureAwait(System.Boolean)] //public ConfiguredTaskAwaitable ConfigureAwait(bool continueOnCapturedContext) //{ //} public static Task Delay(int millisecondsDelay) { // X:\jsc.svn\examples\javascript\Test\TestTaskDelay\TestTaskDelay\ApplicationControl.cs // "X:\jsc.svn\examples\javascript\Test\TestTaskDelay\TestTaskDelay.sln" // X:\jsc.svn\examples\javascript\async\ColorDisco\ColorDisco\ApplicationWebService.cs // tested by? var t = new __Task { }; //Native.setTimeout new ScriptCoreLib.JavaScript.Runtime.Timer( delegate { t.InternalSetCompleteAndYield(); } ).StartTimeout(millisecondsDelay); return(t); }
// https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/20151102/csv // Z:\jsc.svn\examples\javascript\chrome\hybrid\ChromeHybridCaptureAE\Application.cs static Application() { #region document if (Native.document != null) { // patch the awaiter.. Console.SetOut(new xConsole()); // also. all workers we will be creating will need to start to expect switch commands... // how can we tap in them? //__worker_onfirstmessage: {{ // ManagedThreadId = 10, href = https://192.168.1.196:13946/view-source#worker, // MethodTargetTypeIndex = type$PgZysaxv_bTu4GEkwmJdJrQ, // MethodTargetType = ___ctor_b__1_5_d, // MethodToken = jwsABpdwBjGQu09dvBXjxw, // MethodType = FuncOfObjectToObject, // stateTypeHandleIndex = null, // stateType = null, // state = [object Object], // IsIProgress = false }} // // can we start a task, yet also have special access for the posted messages? // what about threads that did not hop to background? // dont they want to hop to background? HopToThreadPoolAwaitable.VirtualOnCompleted = continuation => { Action<ShadowIAsyncStateMachine> MoveNext0 = null; // async dont like ref? var shadowstate = ShadowIAsyncStateMachine.FromContinuation(continuation, ref MoveNext0); var MoveNext = MoveNext0; Console.WriteLine("enter HopToThreadPoolAwaitable.VirtualOnCompleted " + new { shadowstate.state }); // post a message to the document var xx = new __Task.InternalTaskExtensionsScope { InternalTaskExtensionsScope_function = continuation }; var x = new __Task<object>(); // reusing thread init for generic task start, although, resuming needs special implementation.. x.InternalInitializeInlineWorker( new Action(xx.f), //action, default(object), default(CancellationToken), default(TaskCreationOptions), TaskScheduler.Default, yield: (worker, e) => { // like operator for JSON? //Console.WriteLine("enter HopToThreadPoolAwaitable InternalInitializeInlineWorker yield"); var data = new { HopToUIAwaitable = new { // state to hop back shadowstate = default(ShadowIAsyncStateMachine) } }; data = (dynamic)e.data; //if (data.HopToUIAwaitable ) if (data.HopToUIAwaitable == null) return; // time to hop back on continuation? Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("enter HopToThreadPoolAwaitable yield HopToUIAwaitable, resume state? " + new { data.HopToUIAwaitable.shadowstate.state }); Console.ForegroundColor = ConsoleColor.Black; //enter HopToThreadPoolAwaitable yield HopToUIAwaitable //worker Task Run function has returned {{ value_Task = null, value_TaskOfT = null }} //__Task.InternalStart inner complete {{ yield = {{ value = null }} }} // the worker should be in a suspended state, as we may want to jump back? // MoveNext(data.HopToUIAwaitable.shadowstate); } ); x.Start(); }; return; } #endregion #region worker if (Native.worker != null) { Console.WriteLine("about to enable HopToUIAwaitable..."); Native.worker.onfirstmessage += e => { Console.WriteLine("enter onfirstmessage"); HopToUIAwaitable.VirtualOnCompleted = continuation => { // first jump out? InternalInlineWorker.InternalOverrideTaskOfT = new TaskCompletionSource<object>().Task; // post a message to the document // um. how can we signal that we are not done? Action<ShadowIAsyncStateMachine> MoveNext = null; // async dont like ref? var shadowstate = ShadowIAsyncStateMachine.FromContinuation(continuation, ref MoveNext); Console.WriteLine("enter HopToUIAwaitable.VirtualOnCompleted, postMessage " + new { shadowstate.state }); // postMessageAsync ? if ui wants to return, instead of restaring this thread? e.postMessage( new { HopToUIAwaitable = new { // state to hop back shadowstate } } ); }; }; return; } #endregion }
static Application() { #region document if (Native.document != null) { // patch the awaiter.. //Console.SetOut(new xConsole()); // also. all workers we will be creating will need to start to expect switch commands... // how can we tap in them? //__worker_onfirstmessage: {{ // ManagedThreadId = 10, href = https://192.168.1.196:13946/view-source#worker, // MethodTargetTypeIndex = type$PgZysaxv_bTu4GEkwmJdJrQ, // MethodTargetType = ___ctor_b__1_5_d, // MethodToken = jwsABpdwBjGQu09dvBXjxw, // MethodType = FuncOfObjectToObject, // stateTypeHandleIndex = null, // stateType = null, // state = [object Object], // IsIProgress = false }} // // can we start a task, yet also have special access for the posted messages? // what about threads that did not hop to background? // dont they want to hop to background? HopToWorker.VirtualOnCompleted = continuation => { Action<ShadowIAsyncStateMachine> MoveNext0 = null; // async dont like ref? var shadowstate = ShadowIAsyncStateMachine.FromContinuation(continuation, ref MoveNext0); var MoveNext = MoveNext0; Console.WriteLine("enter HopToWorker " + new { shadowstate.state }); // post a message to the document var xx = new __Task.InternalTaskExtensionsScope { InternalTaskExtensionsScope_function = continuation }; var x = new __Task<object>(); // reusing thread init for generic task start, although, resuming needs special implementation.. x.InternalInitializeInlineWorker( new Action(xx.f), //action, default(object), default(CancellationToken), default(TaskCreationOptions), TaskScheduler.Default, yield: (worker, e) => { // like operator for JSON? //Console.WriteLine("enter HopToThreadPoolAwaitable InternalInitializeInlineWorker yield"); var data = new { vSetTitle = default(string), HopToUIAwaitable = new { // state to hop back shadowstate = default(ShadowIAsyncStateMachine) } }; data = (dynamic)e.data; //if (data.HopToUIAwaitable ) if (data.vSetTitle != null) { Console.Title = data.vSetTitle; } if (data.HopToUIAwaitable == null) return; // time to hop back on continuation? var that = (TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine)data.HopToUIAwaitable.shadowstate; //Console.ForegroundColor = ConsoleColor.Blue; Console.WriteLine("work about to hop into ui " + new { that.state }); //Console.ForegroundColor = ConsoleColor.Black; //enter HopToThreadPoolAwaitable yield HopToUIAwaitable //worker Task Run function has returned {{ value_Task = null, value_TaskOfT = null }} //__Task.InternalStart inner complete {{ yield = {{ value = null }} }} // the worker should be in a suspended state, as we may want to jump back? // //MoveNext(data.HopToUIAwaitable.shadowstate); #region xAsyncStateMachineType var xAsyncStateMachineType = typeof(Application).Assembly.GetTypes().FirstOrDefault( item => { // safety check 1 //Console.WriteLine(new { sw.ElapsedMilliseconds, item.FullName }); var xisIAsyncStateMachine = typeof(IAsyncStateMachine).IsAssignableFrom(item); if (xisIAsyncStateMachine) { //Console.WriteLine(new { item.FullName, isIAsyncStateMachine }); return item.FullName == that.TypeName; } return false; } ); #endregion var NewStateMachine = FormatterServices.GetUninitializedObject(xAsyncStateMachineType); var isIAsyncStateMachine = NewStateMachine is IAsyncStateMachine; var NewStateMachineI = (IAsyncStateMachine)NewStateMachine; #region 1__state xAsyncStateMachineType.GetFields( System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance ).WithEach( AsyncStateMachineSourceField => { Console.WriteLine(new { AsyncStateMachineSourceField }); if (AsyncStateMachineSourceField.Name.EndsWith("1__state")) { AsyncStateMachineSourceField.SetValue( NewStateMachineI, that.state ); } var xStringField = that.StringFields.AsEnumerable().FirstOrDefault( f => DecoratedString(f.FieldName) == DecoratedString(AsyncStateMachineSourceField.Name) ); if (xStringField != null) { // once we are to go back to client. we need to reverse it? AsyncStateMachineSourceField.SetValue( NewStateMachineI, xStringField.value ); // next xml? // before lets send our strings back with the new state! // what about exceptions? } } ); #endregion //new IHTMLPre { // "inside iframe invoke state" // }.AttachToDocument(); NewStateMachineI.MoveNext(); } ); x.Start(); }; return; } #endregion #region worker if (Native.worker != null) { Console.WriteLine("about to enable HopToUI..."); Native.worker.onfirstmessage += e => { Console.WriteLine("enter onfirstmessage"); ScriptCoreLib.JavaScript.BCLImplementation.System.__Console.vSetTitle = value => { e.postMessage( new { vSetTitle = value } ); }; HopToUI.VirtualOnCompleted = continuation => { // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/201511/20151102/hoptoui // first jump out? InternalInlineWorker.InternalOverrideTaskOfT = new TaskCompletionSource<object>().Task; // post a message to the document // um. how can we signal that we are not done? //Action<ShadowIAsyncStateMachine> MoveNext = null; // async dont like ref? //var shadowstate = ShadowIAsyncStateMachine.FromContinuation(continuation, ref MoveNext); var r = TestSwitchToServiceContextAsync.ShadowIAsyncStateMachine.ResumeableFromContinuation(continuation); Console.WriteLine("enter HopToUI, postMessage " + new { r.shadowstate.state }); // postMessageAsync ? if ui wants to return, instead of restaring this thread? e.postMessage( new { HopToUIAwaitable = new { // state to hop back r.shadowstate } } ); }; }; return; } #endregion }
public __TaskCompletionSource() { this.InternalTask = new __Task <TResult> { InternalStart = null }; }
public Task <TResult> ContinueWhenAll <TAntecedentResult, TResult>( Task <TAntecedentResult>[] tasks, Func <Task <TAntecedentResult>[], TResult> continuationFunction, CancellationToken cancellationToken, TaskContinuationOptions continuationOptions, TaskScheduler scheduler) { //Console.WriteLine("ContinueWhenAll " + new { tasks.Length, scheduler, Thread.CurrentThread.ManagedThreadId }); var t = new __Task <TResult> { InternalStart = null }; var cstart = 0; var cstop = 0; #region ContinueWhenAll_yield Action ContinueWhenAll_yield = delegate { // how can we pass array of tasks to background? //Console.WriteLine("ContinueWhenAll_yield " + new { scheduler }); #region GUI if (scheduler != null) { var r = continuationFunction(tasks); t.InternalSetCompleteAndYield(r); return; } #endregion // X:\jsc.svn\examples\javascript\appengine\Test\AppEngineFirstEverWebServiceTask\AppEngineFirstEverWebServiceTask\ApplicationWebService.cs var xfunction = continuationFunction; var MethodType = typeof(FuncOfTaskOfObjectArrayToObject).Name; #region MethodToken var MethodToken = ((__MethodInfo)xfunction.Method).InternalMethodToken; if (xfunction.Target != null) { if (xfunction.Target != Native.self) { // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs Delegate InternalTaskExtensionsScope_function = (xfunction.Target as dynamic).InternalTaskExtensionsScope_function; if (InternalTaskExtensionsScope_function == null) { var message = "inline scope sharing not yet implemented"; Console.WriteLine(message); throw new InvalidOperationException(message); } MethodToken = ((__MethodInfo)InternalTaskExtensionsScope_function.Method).InternalMethodToken; } } #endregion #region xdata___string // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs dynamic xdata___string = new object(); // how much does this slow us down? // connecting to a new scope, we need a fresh copy of everything // we can start with strings foreach (ExpandoMember nn in Expando.Of(InternalInlineWorker.__string).GetMembers()) { if (nn.Value != null) { xdata___string[nn.Name] = nn.Value; } } #endregion // is this correct? // OBSOLETE ! needs more tests. what about scope sharing? var w = new global::ScriptCoreLib.JavaScript.DOM.Worker( InternalInlineWorker.GetScriptApplicationSourceForInlineWorker() //global::ScriptCoreLib.JavaScript.DOM.Worker.ScriptApplicationSourceForInlineWorker ); var TaskArray = tasks.Select(k => new { k.Result }).ToArray(); Console.WriteLine(new { TaskArray = TaskArray.Length }); //Debugger.Break(); #region postMessage w.postMessage( new { InternalInlineWorker.InternalThreadCounter, MethodToken, MethodType, //state = state, // pass the result for reconstruction // task[0].Result TaskArray, __string = (object)xdata___string } , e => { // what kind of write backs do we expect? // for now it should be console only // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs dynamic zdata = e.data; #region AtWrite string AtWrite = zdata.AtWrite; if (!string.IsNullOrEmpty(AtWrite)) { Console.Write(AtWrite); } #endregion #region __string var zdata___string = (object)zdata.__string; if (zdata___string != null) { #region __string dynamic target = InternalInlineWorker.__string; var m = Expando.Of(zdata___string).GetMembers(); foreach (ExpandoMember nn in m) { Console.WriteLine("Worker has sent changes " + new { nn.Name }); target[nn.Name] = nn.Value; } #endregion } #endregion #region yield dynamic yield = zdata.yield; if ((object)yield != null) { object value = yield.value; //Console.WriteLine("__Task.InternalStart inner complete " + new { yield = new { value } }); t.InternalSetCompleteAndYield((TResult)value); //w.terminate(); } #endregion } ); #endregion InternalInlineWorker.InternalThreadCounter++; }; #endregion #region ContinueWhenAll_yield foreach (__Task <TAntecedentResult> item in tasks) { cstart++; //Console.WriteLine("ContinueWhenAll before ContinueWith " + new { cstart, tasks.Length, Thread.CurrentThread.ManagedThreadId }); item.ContinueWith( task => { cstop++; //Console.WriteLine("ContinueWhenAll ContinueWith yield " + new { cstop, tasks.Length, Thread.CurrentThread.ManagedThreadId }); if (cstop == tasks.Length) { //Console.WriteLine("before ContinueWhenAll_yield"); ContinueWhenAll_yield(); //Console.WriteLine("after ContinueWhenAll_yield"); } }, // just for the watchdog scheduler: TaskScheduler.FromCurrentSynchronizationContext() ); } #endregion return(t); }
// who is calling? // triggered by InternalInvoke static void __worker_onfirstmessage( MessageEvent e, int InternalThreadCounter, object data___string, bool[] MethodTargetObjectDataIsProgress, object[] MethodTargetObjectData, // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2014/201411/20141112 object[] MethodTargetObjectDataTypes, object MethodTargetTypeIndex, // set by ? string MethodToken, string MethodType, object state_ObjectData, object stateTypeHandleIndex, object state, bool IsIProgress, //bool IsTuple2_Item1_IsIProgress, __Task<object>[] TaskArray ) { // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/201501/20150111 #region ConsoleFormWriter var w = new InternalInlineWorkerTextWriter(); var o = Console.Out; Console.SetOut(w); w.AtWrite = AtWrite => { // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs //dynamic zdata = new object(); //zdata.AtWrite = x; // working with multiple threads, keep the id in the log! // () means we are setting the thread up... [] is the thread AtWrite = "W[" + Thread.CurrentThread.ManagedThreadId + "] " + AtWrite; var zdata = new { AtWrite }; foreach (MessagePort port in e.ports) { port.postMessage((object)zdata, new MessagePort[0]); } }; #endregion __Thread.InternalCurrentThread.ManagedThreadId = InternalThreadCounter; __Thread.InternalCurrentThread.IsBackground = true; // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs dynamic self = Native.self; var stateType = default(Type); if (stateTypeHandleIndex != null) stateType = Type.GetTypeFromHandle(new __RuntimeTypeHandle((IntPtr)self[stateTypeHandleIndex])); // X:\jsc.svn\examples\javascript\async\AsyncNonStaticHandler\AsyncNonStaticHandler\Application.cs var MethodTargetType = default(Type); if (MethodTargetTypeIndex != null) MethodTargetType = Type.GetTypeFromHandle(new __RuntimeTypeHandle((IntPtr)self[MethodTargetTypeIndex])); // stateType = <Namespace>.xFoo, // MethodTargetTypeIndex = type$GV0nCx_bM8z6My5NDh7GXlQ, Console.WriteLine( "__worker_onfirstmessage: " + new { Thread.CurrentThread.ManagedThreadId, Native.worker.location.href, MethodTargetTypeIndex, MethodTargetType, MethodToken, MethodType, //IsTuple2_Item1_IsIProgress, // X:\jsc.svn\examples\javascript\test\TestTypeHandle\TestTypeHandle\Application.cs stateTypeHandleIndex, stateType, state, IsIProgress, //MethodTokenReference } ); #region MethodTokenReference var MethodTokenReference = default(IFunction); var MethodTarget = default(object); if (MethodTargetType == null) { MethodTokenReference = IFunction.Of(MethodToken); } else { MethodTarget = FormatterServices.GetUninitializedObject(MethodTargetType); var MethodTargetTypeSerializableMembers = FormatterServices.GetSerializableMembers(MethodTargetType); // X:\jsc.svn\examples\javascript\async\test\TestWorkerScopeProgress\TestWorkerScopeProgress\Application.cs for (int i = 0; i < MethodTargetTypeSerializableMembers.Length; i++) { var xMember = MethodTargetTypeSerializableMembers[i] as FieldInfo; var xObjectData = MethodTargetObjectData[i]; var xMethodTargetObjectDataTypeIndex = MethodTargetObjectDataTypes[i]; var xIsProgress = MethodTargetObjectDataIsProgress[i]; // X:\jsc.svn\examples\javascript\chrome\apps\ChromeTCPServer\ChromeTCPServer\Application.cs // does our chrome tcp server get the damn path? // https://sites.google.com/a/jsc-solutions.net/work/knowledge-base/15-dualvr/20150428 //Console.WriteLine(new { xMember, xMethodTargetObjectDataTypeIndex, xObjectData, xIsProgress }); Console.WriteLine(new { xMember, xMethodTargetObjectDataTypeIndex, xIsProgress }); // need to resurrect the semaphores! // X:\jsc.svn\examples\javascript\async\Test\TestSemaphoreSlim\TestSemaphoreSlim\ApplicationControl.cs #region MethodTargetObjectDataIsProgress // cant we use xMethodTargetObjectDataType instead? if (xIsProgress) { var ii = i; MethodTargetObjectData[ii] = new __Progress<object>( ProgressEvent => { // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs dynamic zdata = new object(); zdata.MethodTargetObjectDataProgressReport = new { ProgressEvent, ii }; foreach (MessagePort port in e.ports) { port.postMessage((object)zdata, new MessagePort[0]); } //Console.WriteLine(new { MethodTargetTypeSerializableMember, MethodTargetTypeSerializableMemberIsProgress, ProgressEvent }); } ); } #endregion else { var xMethodTargetObjectDataType = default(Type); if (xMethodTargetObjectDataTypeIndex != null) xMethodTargetObjectDataType = Type.GetTypeFromHandle(new __RuntimeTypeHandle((IntPtr)self[xMethodTargetObjectDataTypeIndex])); // now we know the type. should we review it? if (xMethodTargetObjectDataType != null) { var scope2copy = FormatterServices.GetUninitializedObject(xMethodTargetObjectDataType); //shall we copy the members too? //FormatterServices.PopulateObjectMembers(scope2copy, scope2TypeSerializableMembers, scope2ObjectData); MethodTargetObjectData[i] = scope2copy; #region __SemaphoreSlim // X:\jsc.svn\examples\javascript\async\Test\TestSemaphoreSlim\TestSemaphoreSlim\ApplicationControl.cs var xSemaphoreSlim = scope2copy as __SemaphoreSlim; if (xSemaphoreSlim != null) { // we now have to complete the entanglement. we have the caller on the UI. Action<string> UIWriteLine0 = text => { // mimick roslyn syntax Console.WriteLine("$" + xMember.Name + " " + text); }; //xSemaphoreSlim.InternalIsEntangled = true; #region InternalVirtualWaitAsync var xInternalVirtualWaitAsync = default(TaskCompletionSource<object>); xSemaphoreSlim.InternalVirtualWaitAsync += continuation => { UIWriteLine0("enter xSemaphoreSlim.InternalVirtualWaitAsync, worker is now awaiting for signal " + new { xSemaphoreSlim.Name }); xInternalVirtualWaitAsync = continuation; }; // at this point lets call the UI to set up a new signal channel.. //new MessageChannel(); var c = new MessageChannel(); c.port1.onmessage += ce => { // ui has released? if (xInternalVirtualWaitAsync == null) { // what if the thread is not yet awaiting? UIWriteLine0("ui has sent a release signal, yet nobody awaiting"); return; } UIWriteLine0("ui has sent a release signal, resync"); // we should have byte fields now. // next strings as in thread hopping... dynamic data = ce.data; #region read xSemaphoreSlim_ByteArrayFields { __Task.xByteArrayField[] xSemaphoreSlim_ByteArrayFields = data.xSemaphoreSlim_ByteArrayFields; // X:\jsc.svn\examples\javascript\async\test\TestBytesToSemaphore\TestBytesToSemaphore\Application.cs if (xSemaphoreSlim_ByteArrayFields != null) foreach (var item in xSemaphoreSlim_ByteArrayFields) { var xFieldInfo = (FieldInfo)MethodTargetTypeSerializableMembers[item.index]; // X:\jsc.svn\examples\javascript\chrome\apps\ChromeThreadedCameraTracker\ChromeThreadedCameraTracker\Application.cs // can we set the value? UIWriteLine0("worker resync " + new { item.index, //item.Name, xFieldInfo = xFieldInfo.Name, //item.value }); xFieldInfo.SetValue( MethodTarget, // null? item.value ); } } #endregion xInternalVirtualWaitAsync.SetResult(null); }; c.port1.start(); c.port2.start(); UIWriteLine0("will set up the signal channel"); foreach (var p in e.ports) { p.postMessage( new { xSemaphoreSlim = xMember.Name }, transfer: new[] { c.port2 } ); } #endregion #region InternalVirtualRelease xSemaphoreSlim.InternalVirtualRelease += delegate { UIWriteLine0("enter xSemaphoreSlim.InternalVirtualRelease, will send a signal to ui..."); // worker needs sync data about now. // the ui would be happy to have the latest version of the data. // this is tricky. we would really need to know which data fields have changed by now // and what will happen if the data was also changed on the ui. // technically we are doing a merge conflict resolver... // this is somewhat the same situation, we alrady have // when entering a worker // when exiting a worker // when hoping to or from a worker. // what data fields do we have to upload yo ui? // how much IL analysis is available for us to know what to sync // we should not sync fields that wont be used on the ui // the thread hop looks at strings only right now, as they are immputable yet primitive // what about bytewarrays? // X:\jsc.svn\examples\javascript\async\test\TestBytesFromSemaphore\TestBytesFromSemaphore\Application.cs #region xSemaphoreSlim_ByteArrayFields var xSemaphoreSlim_ByteArrayFields = new List<__Task.xByteArrayField>(); var MethodTargetTypeSerializableMembers_index = 0; foreach (FieldInfo item in MethodTargetTypeSerializableMembers) { // how would we know if the array is a byte array? // FieldType is not exactly available yet //Console.WriteLine("worker resync candidate " + new { item.Name, item.FieldType, item.FieldType.IsArray }); var item_value = item.GetValue(MethodTarget); if (item_value != null) { var item_value_constructor = Expando.Of(item_value).constructor; var item_value_IsByteArray = Native.self_Uint8ClampedArray == item_value_constructor; if (item_value_IsByteArray) { var value = (byte[])item_value; xSemaphoreSlim_ByteArrayFields.Add( new __Task.xByteArrayField { index = MethodTargetTypeSerializableMembers_index, // keep name for diagnostics Name = item.Name, value = value } ); UIWriteLine0("worker resync xByteArrayField candidate " + new { item.Name, value.Length }); } } MethodTargetTypeSerializableMembers_index++; } #endregion foreach (var p in e.ports) { p.postMessage( new { xSemaphoreSlim = xMember.Name, xSemaphoreSlim_ByteArrayFields = xSemaphoreSlim_ByteArrayFields.ToArray() } ); } }; #endregion } #endregion } } } FormatterServices.PopulateObjectMembers( MethodTarget, MethodTargetTypeSerializableMembers, MethodTargetObjectData ); // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs MethodTokenReference = (MethodTarget as dynamic)[MethodToken]; } // what if we are being called from within a secondary app? // stateTypeHandleIndex = type$XjKww8iSKT_aFTpY_bSs5vBQ, if (MethodTokenReference == null) { // tested at // X:\jsc.svn\examples\javascript\WorkerInsideSecondaryApplication\WorkerInsideSecondaryApplication\Application.cs // X:\jsc.svn\examples\javascript\Test\TestHopToThreadPoolAwaitable\TestHopToThreadPoolAwaitable\Application.cs // why? throw new InvalidOperationException( new { MethodToken } + " function is not available at " + new { Native.worker.location.href } ); } #endregion //Console.WriteLine( // new // { // MethodTokenReference, // Thread.CurrentThread.ManagedThreadId // } // ); // whats the type? #region xstate var xstate = default(object); if (stateType != null) { xstate = FormatterServices.GetUninitializedObject(stateType); var xstate_SerializableMembers = FormatterServices.GetSerializableMembers(stateType); FormatterServices.PopulateObjectMembers( xstate, xstate_SerializableMembers, (object[])state_ObjectData ); // MethodType = FuncOfObjectToObject //Console.WriteLine("as FuncOfObjectToObject"); } #endregion #region CreateProgress Func<__Progress<object>> CreateProgress = () => new __Progress<object>( value => { //Console.WriteLine("__IProgress_Report " + new { value }); // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs dynamic zdata = new object(); zdata.__IProgress_Report = new { value }; foreach (MessagePort port in e.ports) { port.postMessage((object)zdata, new MessagePort[0]); } } ); // X:\jsc.svn\examples\javascript\async\Test\TestWorkerProgress\TestWorkerProgress\Application.cs if (IsIProgress) xstate = CreateProgress(); #endregion #region __string // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs dynamic target = __string; var m = Expando.Of(data___string).GetMembers(); // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2013/201308/20130826-domainmemory foreach (ExpandoMember nn in m) { target[nn.Name] = nn.Value; var trigger = "set_" + nn.Name; var trigger_default = IFunction.Of(trigger); (Native.self as dynamic)[trigger] = IFunction.OfDelegate( new Action<string>( Value => { if (nn.Value == Value) return; trigger_default.apply(null, Value); #region sync one field only { dynamic zdata = new object(); dynamic zdata___string = new object(); zdata.__string = zdata___string; zdata___string[nn.Name] = Value; // prevent sync via diff nn.Value = Value; foreach (MessagePort port in e.ports) { port.postMessage((object)zdata, new MessagePort[0]); } } #endregion } ) ); } #endregion { // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2013/201308/20130828-thread-run // for now we only support static calls // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs dynamic zdata = new object(); if (MethodType == typeof(ActionOfDedicatedWorkerGlobalScope).Name) { MethodTokenReference.apply(null, Native.worker); } else if (MethodType == typeof(FuncOfObjectToObject).Name) { Console.WriteLine("worker Task Run function call, FuncOfObjectToObject, will invoke MethodTokenReference"); #region FuncOfObjectToObject // X:\jsc.svn\examples\javascript\test\TestTaskStartToString\TestTaskStartToString\Application.cs // X:\jsc.svn\examples\javascript\async\test\TestTaskRun\TestTaskRun\Application.cs // X:\jsc.svn\examples\javascript\Test\TestGetUninitializedObject\TestGetUninitializedObject\Application.cs var value = MethodTokenReference.apply(MethodTarget, xstate); Console.WriteLine("worker Task Run function call, FuncOfObjectToObject, will invoke MethodTokenReference " + new { value }); // X:\jsc.svn\examples\javascript\async\test\TaskAsyncTaskRun\TaskAsyncTaskRun\Application.cs // whatif its an Action not a Func? //enter HopToThreadPoolAwaitable yield HopToUIAwaitable //worker Task Run function has returned {{ value_Task = null, value_TaskOfT = null }} //__Task.InternalStart inner complete {{ yield = {{ value = null }} }} var value_Task = value as __Task; var value_TaskOfT = value as __Task<object>; // if we are in a hop. allow the return task to be overriden. if (InternalOverrideTaskOfT != null) value_TaskOfT = InternalOverrideTaskOfT; // 0:25611ms Task Run function has returned { value_Task = [object Object], value_TaskOfT = [object Object] } //Console.WriteLine("worker Task Run function has returned " + new { value_Task, value_TaskOfT, InternalOverrideTaskOfT }); // 0:4284ms Task Run function has returned { value_Task = { IsCompleted = 1, Result = }, value_TaskOfT = { IsCompleted = 1, Result = } } // 0:5523ms Task Run function has returned { value_Task = { IsCompleted = false, Result = }, value_TaskOfT = { IsCompleted = false, Result = } } if (value_TaskOfT != null) { // special situation // if IsCompleted, called twice? or heard twice? value_TaskOfT.ContinueWith( t => { //Console.WriteLine("worker Task Run ContinueWith " + new { t }); // X:\jsc.svn\examples\javascript\Test\Test435CoreDynamic\Test435CoreDynamic\Class1.cs dynamic zzdata = new object(); // null? if (t.Result == null) { zzdata.ContinueWithResult = new { t.Result }; foreach (MessagePort port in e.ports) { port.postMessage((object)zzdata, new MessagePort[0]); } return; } var ResultType = t.Result.GetType(); var ResultTypeIndex = __Type.GetTypeIndex("workerResult", ResultType); var ResultTypeSerializableMembers = FormatterServices.GetSerializableMembers(ResultType); var ResultObjectData = FormatterServices.GetObjectData(t.Result, ResultTypeSerializableMembers); var ContinueWithResult = new { ResultTypeIndex, ResultObjectData, t.Result }; zzdata.ContinueWithResult = ContinueWithResult; foreach (MessagePort port in e.ports) { port.postMessage((object)zzdata, new MessagePort[0]); } } ); } else { if (value_Task != null) { // X:\jsc.svn\examples\javascript\async\test\TestWorkerScopeProgress\TestWorkerScopeProgress\Application.cs throw new NotImplementedException(); } else { var yield = new { value }; //Console.WriteLine(new { yield }); Console.WriteLine("worker Task Run function call, FuncOfObjectToObject, will yield? " + new { value_Task, value_TaskOfT }); zdata.yield = yield; } } #endregion // now what? } else if (MethodType == typeof(FuncOfTaskToObject).Name) { Console.WriteLine("bugcheck FuncOfTaskToObject ?"); // tested by? #region FuncOfTaskToObject // need to reconstruct the caller task? var value = MethodTokenReference.apply(null, TaskArray.Single()); var yield = new { value }; //Console.WriteLine(new { yield }); zdata.yield = yield; #endregion // now what? } else if (MethodType == typeof(FuncOfTaskOfObjectArrayToObject).Name) { // tested by? #region FuncOfTaskOfObjectArrayToObject // need to reconstruct the caller task? Console.WriteLine("__worker_onfirstmessage: " + new { TaskArray = TaskArray.Length }); //Debugger.Break(); var args = new object[] { TaskArray }; var value = MethodTokenReference.apply( o: null, // watch out args: args ); var yield = new { value }; //Console.WriteLine(new { yield }); zdata.yield = yield; #endregion // now what? } #region [sync] diff and upload changes to DOM context, the latest now { dynamic zdata___string = new object(); zdata.__string = zdata___string; foreach (ExpandoMember nn in m) { string Value = (string)Expando.InternalGetMember((object)target, nn.Name); // this is preferred: //string Value = target[nn.Name]; if (Value != nn.Value) { zdata___string[nn.Name] = Value; } } } #endregion //e.post foreach (MessagePort port in e.ports) { port.postMessage((object)zdata, new MessagePort[0]); } } }