Пример #1
0
 public void DoWork(MarshaledResultSetter <string> callback)
 {
     ThreadPool.QueueUserWorkItem(delegate
     {
         Thread.SpinWait(500000000);
         callback.SetResult(AppDomain.CurrentDomain.FriendlyName);
     });
 }
Пример #2
0
 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()
             });
         });
 }
Пример #3
0
        /// <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);
            });
        }
Пример #4
0
        /// <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);
            });
        }
Пример #5
0
        /// <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);
            });
        }
Пример #6
0
        /// <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);
            });
        }