public void DoWork(MarshaledResultSetter <string> callback) { ThreadPool.QueueUserWorkItem(delegate { Thread.SpinWait(500000000); callback.SetResult(AppDomain.CurrentDomain.FriendlyName); }); }
public void NotifyOnCounterChange(MarshaledResultSetter<CounterChangeInfo> callback) { Task.WhenAny(this.counters.Select(c => c.ReceiveAsync())) .ContinueWith(delegate { callback.SetResult(new CounterChangeInfo { NewValues = this.counters .Select(c => new { c.Key, Result = c.ReturnAndFlushIfReceived() }) .Where(x => x.Result != null) .Select(x => new KeyValuePair<string, int>(x.Key, x.Result.Value)) .ToList() }); }); }
/// <summary> /// Compiles the program in memory and load it (to use it later) or returns the build errors. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <returns>Returns the build errors, or null if it succeed.</returns> internal void Build(MarshaledResultSetter <AggregateException> callback) { Requires.NotNull(_middleware, nameof(_middleware)); if (DebugMode) { throw new UnexpectedException(new Exception(L.BaZic.Runtime.BaZicInterpreter.CannotBuildAfterStartDebug)); } CheckState(BaZicInterpreterState.Ready, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); if (ProgramIsOptimized) { throw new InvalidOperationException(L.BaZic.Runtime.BaZicInterpreter.CannotRunOptimizedProgramInRelease); } Error = null; ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Running)); AggregateException buildErrors = null; var currentCulture = LocalizationHelper.GetCurrentCulture(); _mainInterpreterTask = Task.Run(() => { LocalizationHelper.SetCurrentCulture(currentCulture, false, false); _compilerResult = Build(BaZicCompilerOutputType.DynamicallyLinkedLibrary, string.Empty, string.Empty, string.Empty, false); if (_compilerResult.BuildErrors != null) { buildErrors = _compilerResult.BuildErrors; ChangeState(this, new UnexpectedException(_compilerResult.BuildErrors)); } else { _assemblySandbox.LoadAssembly(_compilerResult.Assembly, false); _compilerResult.Dispose(); _releaseModeForced = true; ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Stopped)); } }); _mainInterpreterTask.ContinueWith((task) => { callback.SetResult(buildErrors); }); }
/// <summary> /// Invoke a public method accessible from outside of the interpreter (EXTERN FUNCTION) in Release mode. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <param name="verbose">Defines if the verbose mode must be enabled or not.</param> /// <param name="methodName">The name of the method.</param> /// <param name="awaitIfAsync">Await if the method is maked as asynchronous.</param> /// <param name="args">The arguments to pass to the method.</param> /// <returns>Returns the result of the invocation (a <see cref="Task"/> in the case of a not awaited asynchronous method, or the value returned by the method).</returns> private void InvokeMethodRelease(MarshaledResultSetter <object> callback, bool verbose, string methodName, bool awaitIfAsync, object[] args) { var currentCulture = LocalizationHelper.GetCurrentCulture(); var thread = Task.Run(() => { if (State == BaZicInterpreterState.Preparing) { // Wait for running. WaitForState(BaZicInterpreterState.Running, BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); } if (State == BaZicInterpreterState.Running) { // Wait for having being idle. WaitForState(BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); } if (_forceStop) { // The state is Stopped and it has been requested by the user (command await Stop()) or the interpreter is disposing. return(null); } CheckState(BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); RunningStateManager.StartsExternMethod(); object result = null; ThreadHelper.RunOnStaThread(() => { try { LocalizationHelper.SetCurrentCulture(currentCulture, false, false); ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Running)); if (Verbose) { ChangeState(this, new BaZicInterpreterStateChangeEventArgs(L.BaZic.Runtime.CompiledProgramRunner.FormattedInvokeMethod(methodName))); } result = _releaseModeRuntime.InvokeMethod(methodName, args); if (result != null && result is Task && awaitIfAsync) { var task = (Task)result; task.ConfigureAwait(false).GetAwaiter().GetResult(); if (result.GetType().IsGenericType) { result = ((dynamic)task).Result; } else { result = null; }; } } catch (Exception exception) { CoreHelper.ReportException(exception); if (!_ignoreException) { ChangeState(this, new UnexpectedException(exception)); } _ignoreException = false; } finally { GC.Collect(); GC.WaitForPendingFinalizers(); } }); return(result); }); var t = thread.ContinueWith((task) => { RunningStateManager.StopsExternMethod(); RunningStateManager.UpdateState(); callback.SetResult(task.Result); }); }
/// <summary> /// Invoke a public method accessible from outside of the interpreter (EXTERN FUNCTION) in Debug mode. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <param name="verbose">Defines if the verbose mode must be enabled or not.</param> /// <param name="methodName">The name of the method.</param> /// <param name="awaitIfAsync">Await if the method is maked as asynchronous.</param> /// <param name="args">The arguments to pass to the method.</param> /// <returns>Returns the result of the invocation (a <see cref="Task"/> in the case of a not awaited asynchronous method, or the value returned by the method).</returns> private async void InvokeMethodDebug(MarshaledResultSetter <object> callback, bool verbose, string methodName, bool awaitIfAsync, object[] args) { DebugMode = true; if (State == BaZicInterpreterState.Ready || State == BaZicInterpreterState.Stopped || State == BaZicInterpreterState.StoppedWithError) { // Creates a new ProgramInterpreter. var privateCallback = new MarshaledResultSetter(); var action = new Action(() => { LoadAssemblies(); if (State == BaZicInterpreterState.Preparing) { var executionFlowIdProgram = RunningStateManager.AddCallStackForUnwaitedMethodInvocation(); ProgramInterpreter = new ProgramInterpreter(this, Program, executionFlowIdProgram); ProgramInterpreter.InitializeGlobalState(); ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Idle)); } }); Start(privateCallback, action, verbose); await privateCallback.Task; } var currentCulture = LocalizationHelper.GetCurrentCulture(); var thread = Task.Run(() => { object result = null; try { LocalizationHelper.SetCurrentCulture(currentCulture, false, false); Task.Delay(500).ConfigureAwait(false).GetAwaiter().GetResult(); if (State == BaZicInterpreterState.Preparing) { // Wait for running. WaitForState(BaZicInterpreterState.Running, BaZicInterpreterState.Idle); } if (State == BaZicInterpreterState.Running) { // Wait for having being idle. WaitForState(BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); if (_forceStop) { // The state is Stopped and it has been requested by the user (command await Stop()) or the interpreter is disposing. return(null); } } CheckState(BaZicInterpreterState.Idle, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); var arguments = new List <PrimitiveExpression>(); if (args != null) { foreach (var argument in args) { arguments.Add(new PrimitiveExpression(argument)); } } RunningStateManager.StartsExternMethod(); var executionFlowId = RunningStateManager.AddCallStackForUnwaitedMethodInvocation(); result = ProgramInterpreter.InvokeMethod(executionFlowId, methodName, awaitIfAsync, arguments.ToArray()); } catch (Exception exception) { CoreHelper.ReportException(exception); if (!_ignoreException) { ChangeState(this, new UnexpectedException(exception)); } _ignoreException = false; } finally { RunningStateManager.StopsExternMethod(); RunningStateManager.UpdateState(); GC.Collect(); GC.WaitForPendingFinalizers(); } return(result); }); var t = thread.ContinueWith((task) => { callback.SetResult(task.Result); }); }
/// <summary> /// Compiles the program in memory and save it on the hard drive or returns the build errors. /// </summary> /// <param name="callback">The cross-AppDomain task proxy.</param> /// <param name="outputType">Defines the type of assembly to generate</param> /// <param name="outputPath">The full path to the .exe or .dll file to create if the build succeed.</param> /// <param name="assemblyName">Defines the name of the assembly to generate.</param> /// <param name="assemblyVersion">Defines the version of the assembly.</param> /// <param name="assemblyCopyright">Defines the copyright of the assembly.</param> /// <param name="releaseMode">Defines whether the compiler must build in release mode or debug mode.</param> /// <returns>Returns the build errors, or null if it succeed.</returns> internal void Build(MarshaledResultSetter <AggregateException> callback, BaZicCompilerOutputType outputType, string outputPath, string assemblyName, string assemblyVersion, string assemblyCopyright, bool releaseMode) { Requires.NotNull(_middleware, nameof(_middleware)); Requires.NotNullOrWhiteSpace(outputPath, nameof(outputPath)); if (DebugMode) { throw new UnexpectedException(new Exception(L.BaZic.Runtime.BaZicInterpreter.CannotBuildAfterStartDebug)); } CheckState(BaZicInterpreterState.Ready, BaZicInterpreterState.Stopped, BaZicInterpreterState.StoppedWithError); if (ProgramIsOptimized) { throw new InvalidOperationException(L.BaZic.Runtime.BaZicInterpreter.CannotRunOptimizedProgramInRelease); } Error = null; ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Running)); AggregateException buildErrors = null; var currentCulture = LocalizationHelper.GetCurrentCulture(); _mainInterpreterTask = Task.Run(() => { LocalizationHelper.SetCurrentCulture(currentCulture, false, false); var outputFile = new FileInfo(outputPath); var directory = outputFile.Directory; if (string.IsNullOrWhiteSpace(outputFile.Extension)) { if (outputType == BaZicCompilerOutputType.DynamicallyLinkedLibrary) { outputFile = new FileInfo(outputPath + ".dll"); } else { outputFile = new FileInfo(outputPath + ".exe"); } } var outputFileName = Path.GetFileNameWithoutExtension(outputPath); var outputPdbFile = new FileInfo(Path.Combine(directory.FullName, outputFileName + ".pdb")); using (var compileResult = Build(outputType, assemblyName, assemblyVersion, assemblyCopyright, releaseMode)) { if (compileResult.BuildErrors != null) { buildErrors = compileResult.BuildErrors; ChangeState(this, new UnexpectedException(buildErrors)); return; } try { if (!directory.Exists) { directory.Create(); } var assembliesToCopy = _assemblySandbox.GetAssemblies().Where(a => a.CopyToLocal).Concat(Program.Assemblies.Where(a => a.CopyToLocal)).Distinct(); foreach (var assembly in assembliesToCopy) { if (File.Exists(assembly.Location)) { File.Copy(assembly.Location, Path.Combine(directory.FullName, Path.GetFileName(assembly.Location))); var pdbFilePath = Path.Combine(Directory.GetParent(assembly.Location).FullName, Path.GetFileNameWithoutExtension(assembly.Location) + ".pdb"); var xmlFilePath = Path.Combine(Directory.GetParent(assembly.Location).FullName, Path.GetFileNameWithoutExtension(assembly.Location) + ".xml"); if (File.Exists(pdbFilePath)) { File.Copy(pdbFilePath, Path.Combine(directory.FullName, Path.GetFileName(pdbFilePath))); } if (File.Exists(xmlFilePath)) { File.Copy(xmlFilePath, Path.Combine(directory.FullName, Path.GetFileName(xmlFilePath))); } } } using (var assemblyFileStream = new FileStream(outputFile.FullName, FileMode.Create)) using (var pdbFileStream = new FileStream(outputPdbFile.FullName, FileMode.Create)) { compileResult.Assembly.WriteTo(assemblyFileStream); compileResult.Pdb.WriteTo(pdbFileStream); } ChangeState(this, new BaZicInterpreterStateChangeEventArgs(BaZicInterpreterState.Stopped)); } catch (Exception exception) { CoreHelper.ReportException(exception); buildErrors = new AggregateException(new List <Exception> { exception }); ChangeState(this, new UnexpectedException(exception)); } } }); _mainInterpreterTask.ContinueWith((task) => { callback.SetResult(buildErrors); }); }