private IEnumerator <object> RemoteCallTask(ProcessInfo process) { var channel = process.GetNamedChannel("remotecall"); var serializer = new JavaScriptSerializer(); while (true) { var fNext = channel.Receive(); using (fNext) yield return(fNext); object[] callTuple = serializer.Deserialize <object[]>(fNext.Result.DecodeAsciiZ()); string scriptName = callTuple[0] as string; string methodName = callTuple[1] as string; object[] rawArguments = callTuple[2] as object[]; long? resultId = null; if (callTuple.Length >= 4) { resultId = Convert.ToInt64(callTuple[3]); } object[] functionArguments; if (rawArguments == null) { functionArguments = new object[] { process }; } else { functionArguments = new object[rawArguments.Length + 1]; functionArguments[0] = process; for (int i = 0; i < rawArguments.Length; i++) { functionArguments[i + 1] = rawArguments[i]; } } ScriptName sn; if (!Program.PythonModuleToScript.TryGetValue(scriptName, out sn)) { sn = new ScriptName(scriptName); } IManagedScript instance = Program.GetScriptInstance(sn); if (instance == null) { LogPrint(process, "Remote call attempted on script '{0}' that isn't loaded.", scriptName ); continue; } IEnumerator <object> resultTask = null; object result = null; Exception error = null; try { result = instance.GetType().InvokeMember( methodName, BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.Public, null, instance, functionArguments ); } catch (Exception ex) { error = ex; } if (error != null) { if (resultId.HasValue) { yield return(SendRemoteCallResult(process, resultId.Value, null, error)); } else { Program.Scheduler.OnTaskError(error); } } else { resultTask = result as IEnumerator <object>; if (resultTask != null) { var fResult = Program.Scheduler.Start( resultTask, TaskExecutionPolicy.RunWhileFutureLives ); process.OwnedFutures.Add(fResult); if (resultId.HasValue) { fResult.RegisterOnComplete((_) => { object r; Exception e; _.GetResult(out r, out e); Program.Scheduler.Start(SendRemoteCallResult(process, resultId.Value, r, e)); }); } } else { if (resultId.HasValue) { yield return(SendRemoteCallResult(process, resultId.Value, result, null)); } } } } }