示例#1
0
        public void OperationAsync()
        {
            AsyncStateMachine stateMachine = new AsyncStateMachine();

            stateMachine.builder = AsyncVoidMethodBuilder.Create();
            stateMachine.builder.Start(ref stateMachine);
        }
示例#2
0
        // Start is called before the first frame update
        void Start()
        {
            inventory = GetComponent <ResourceInventory>().backingInventory;

            timeTracker      = GetComponent <ITimeTracker>();
            optimizer        = new GatherBehaviorOptimizer();
            gatheringWeights = optimizer.generateInitialWeights();

            stateMachine = new AsyncStateMachine <GathererState, GathererBehavior>(GathererState.Gathering);

            stateMachine.registerStateTransitionHandler(GathererState.All, GathererState.All, (x) =>
            {
                objectSeeker.ClearCurrentTarget();
                lastTargetCheckTime = 0;
            }, StateChangeExecutionOrder.StateExit);

            var sellingStateHandler = new SellingStateHandler();

            sellingStateHandler.InstantiateOnObject(this);

            stateMachine.registerGenericHandler(new GatheringStateHandler());
            stateMachine.registerGenericHandler(new GoingHomeStateHandler());
            stateMachine.registerGenericHandler(new WaitTillMarketStateHandler());
            stateMachine.registerGenericHandler(sellingStateHandler);
            stateMachine.registerGenericHandler(new GoingToConsumeHandler());
            stateMachine.registerGenericHandler(new ConsumingStateHandler());
            stateMachine.registerGenericHandler(new DieStateHandler());
            stateMachine.registerGenericHandler(new SleepStateHandler());

            stateMachine.LockStateHandlers();
        }
示例#3
0
        private static Task <long?> GetPageLengthAsync()
        {
            var stateMachine = new AsyncStateMachine
            {
                Builder = AsyncTaskMethodBuilder <long?> .Create(),
                State   = -1
            };

            stateMachine.Builder.Start(ref stateMachine);
            return(stateMachine.Builder.Task);
        }
示例#4
0
        private void Connet_Click(object sender, RoutedEventArgs e)
        {
            AsyncStateMachine stateMachine = new AsyncStateMachine {
                baseWindow = this,
                sender     = sender,
                e          = e,
                builder    = AsyncVoidMethodBuilder.Create(),
                state      = -1
            };

            stateMachine.builder.Start <AsyncStateMachine>(ref stateMachine);
        }
        internal static Task <T> CompiledAsync <T>(T value)
        {
            AsyncStateMachine <T> asyncStateMachine = new AsyncStateMachine <T>()
            {
                Value   = value,
                Builder = AsyncTaskMethodBuilder <T> .Create(),
                State   = -1 // -1 means start.
            };

            asyncStateMachine.Builder.Start(ref asyncStateMachine);
            return(asyncStateMachine.Builder.Task);
        }
示例#6
0
        static async Task Main(string[] args)
        {
            //await Task.FromResul(true);
            var stateMachine = new AsyncStateMachine
            {
                _builder = AsyncTaskMethodBuilder <bool> .Create(),
                _state   = -1
            };

            stateMachine._builder.Start(ref stateMachine);
            var result = stateMachine._builder.Task.Result;
        }
示例#7
0
        public void FactMethodName()
        {
            //await Task.FromResul(100)
            var t = new AsyncStateMachine
            {
                _this    = this,
                _builder = AsyncTaskMethodBuilder <int> .Create(),
                _state   = -1
            };

            t._builder.Start(ref t);
            t._builder.Task.Result.Should().Be(10);
        }
示例#8
0
        public static IStateMachine <TMachineState, TMachineEvent> CreateAsync <TMachineState, TMachineEvent>(
            TMachineState initialState,
            IAsyncStateMachineConfiguration <TMachineState, TMachineEvent> configuration)
        {
            if (configuration is AsyncStateMachineDispatcher <TMachineState, TMachineEvent> dispatcher)
            {
                var synchronizationQueueFactory = new DataFlowSynchronizationQueueFactory();
                var machine = new AsyncStateMachine <TMachineState, TMachineEvent>(initialState, dispatcher, synchronizationQueueFactory);
                return(machine);
            }

            throw new ArgumentException("configuration must not be a custom implementation of the state machine configuration interface.");
        }
        // When an async method is generated by the compiler, it is transformed into something similar than
        // the following method. Of course, it is only present in IL. This C# version is reconstructed from IL.
        private void CalculateOnBackgroundThreadDecompiled(object sender, RoutedEventArgs e)
        {
            var machine = new AsyncStateMachine
            {
                Builder         = AsyncTaskMethodBuilder <long> .Create(),
                State           = -1,
                ToTextBox       = ToTextBox,
                Button          = Button,
                ProgressRing    = ProgressRing,
                ResultTextBlock = ResultTextBlock
            };

            machine.Builder.Start(ref machine);
        }
        // Start is called before the first frame update
        void Start()
        {
            inventory    = GetComponent <ResourceInventory>().backingInventory;
            stateMachine = new AsyncStateMachine <TraderState, TraderBehavior>(TraderState.Initial);

            stateMachine.registerStateTransitionHandler(TraderState.All, TraderState.All, (x) =>
            {
                objectSeeker.ClearCurrentTarget();
            }, StateChangeExecutionOrder.StateExit);

            stateMachine.registerGenericHandler(new InitalStateHandler());
            stateMachine.registerGenericHandler(new TradeTransitStateHandler());
            stateMachine.registerGenericHandler(new TradeExecuteStateHandler());
            stateMachine.LockStateHandlers();
        }
示例#11
0
        void IInterceptor.Intercept(IInvocation invocation)
        {
            var returnType = invocation.Method.ReturnType;
            var builder    = AsyncMethodBuilder.TryCreate(returnType);

            if (builder != null)
            {
                var asyncInvocation = new AsyncInvocation(invocation);
                var stateMachine    = new AsyncStateMachine(asyncInvocation, builder, task: this.InterceptAsync(asyncInvocation));
                builder.Start(stateMachine);
                invocation.ReturnValue = builder.Task();
            }
            else
            {
                this.Intercept(invocation);
            }
        }
示例#12
0
        private static IAwaitableStateMachine <TState, TTrigger> Create <TState, TTrigger>(TState initialState,
                                                                                           AwaitableStateMachineConfiguration <TState, TTrigger> config, bool asyncMachine, TaskScheduler scheduler)
        {
            IAwaitableStateMachine <TState, TTrigger> sm;

            if (asyncMachine)
            {
                sm = new AsyncStateMachine <TState, TTrigger>(initialState, config);
            }
            else
            {
                sm = scheduler == null
                    ? (IAwaitableStateMachine <TState, TTrigger>)
                     new AwaitableStateMachine <TState, TTrigger>(initialState, config)
                    : new AwaitableStateMachineWithScheduler <TState, TTrigger>(initialState, config, scheduler);
            }

            sm.UnhandledTriggerExecuted += InvalidTriggerException <TTrigger, TState> .Throw;
            return(sm);
        }
示例#13
0
            void IAsyncStateMachine.MoveNext()
            {
                int  num1 = State;
                long?contentLength;

                try
                {
                    TaskAwaiter <HttpResponseMessage> awaiter;
                    if (num1 != 0)
                    {
                        _client = new HttpClient();
                        awaiter = _client.GetAsync("http://apress.com").GetAwaiter();
                        if (!awaiter.IsCompleted)
                        {
                            State    = 0;
                            _awaiter = awaiter;
                            AsyncStateMachine stateMachine = this;
                            Builder.AwaitUnsafeOnCompleted(ref awaiter, ref stateMachine);
                            return;
                        }
                    }
                    else
                    {
                        awaiter  = _awaiter;
                        _awaiter = new TaskAwaiter <HttpResponseMessage>();
                        State    = -1;
                    }
                    _responce2    = awaiter.GetResult();
                    _responce1    = _responce2;
                    _responce2    = null;
                    contentLength = _responce1.Content.Headers.ContentLength;
                }
                catch (Exception ex)
                {
                    State = -2;
                    Builder.SetException(ex);
                    return;
                }
                State = -2;
                Builder.SetResult(contentLength);
            }
示例#14
0
            public void MoveNext()
            {
                int num         = _state;
                var taskAwaiter = new CustomAwaiter();

                if (num != 0)
                {
                    if (!taskAwaiter.IsCompleted)
                    {
                        _state       = 0;
                        _taskAwaiter = taskAwaiter;
                        AsyncStateMachine state = this;
                        _builder.AwaitOnCompleted(ref taskAwaiter, ref state);
                        return;
                    }
                }
                var res = taskAwaiter.GetResult();

                taskAwaiter = null;

                _state = -2;
                _builder.SetResult(res);
            }
示例#15
0
        private static bool PrintAsyncStateMachineChain(DebuggerOutput output, AsyncStateMachine node, HashSet <AsyncStateMachine> printedMachines)
        {
            int  nLevel            = 0;
            bool multipleLineBlock = false;

            var loopDetection = new HashSet <AsyncStateMachine>();

            for (AsyncStateMachine?p = node; p is object; p = p.Next)
            {
                printedMachines.Add(p);

                if (nLevel > 0)
                {
                    output.WriteString("..");
                    multipleLineBlock = true;
                }
                else if (p.AlterPrevious is object)
                {
                    output.WriteObjectAddress(p.AlterPrevious.StateMachine.Address);
                    output.WriteString($" <{p.AlterPrevious.State}> * {p.AlterPrevious.StateMachine.Type?.Name} @ ");
                    output.WriteMethodInfo($"{p.AlterPrevious.CodeAddress:x}", p.AlterPrevious.CodeAddress);
                    output.WriteLine(string.Empty);
                    output.WriteString("..");
                    multipleLineBlock = true;
                }
                else if (!p.SwitchToMainThreadTask.IsNull)
                {
                    output.WriteObjectAddress(p.SwitchToMainThreadTask.Address);
                    output.WriteLine(".SwitchToMainThreadAsync");
                    output.WriteString("..");
                    multipleLineBlock = true;
                }

                output.WriteObjectAddress(p.StateMachine.Address);
                string doubleDependentTaskMark = p.DependentCount > 1 ? " * " : " ";
                output.WriteString($" <{p.State}>{doubleDependentTaskMark}{p.StateMachine.Type?.Name} @ ");
                output.WriteMethodInfo($"{p.CodeAddress:x}", p.CodeAddress);
                output.WriteLine(string.Empty);

                if (!loopDetection.Add(p))
                {
                    output.WriteLine("!!Loop task dependencies");
                    break;
                }

                if (p.Next is null && p.BlockedThread.HasValue)
                {
                    output.WriteString("-- ");
                    output.WriteThreadLink(p.BlockedThread.Value);
                    output.WriteString(" - JoinableTask: ");
                    output.WriteObjectAddress(p.BlockedJoinableTask.Address);

                    int state = p.BlockedJoinableTask.ReadField <int>("state");
                    if ((state & 0x20) == 0x20)
                    {
                        output.WriteLine(" SynchronouslyBlockingMainThread");
                    }
                    else
                    {
                        output.WriteLine(string.Empty);
                    }

                    multipleLineBlock = true;
                }

                nLevel++;
            }

            return(multipleLineBlock);
        }
示例#16
0
        private static void GetAllStateMachines(DebuggerContext context, ClrHeap heap, List <AsyncStateMachine> allStateMachines, Dictionary <ulong, AsyncStateMachine> knownStateMachines)
        {
            foreach (var obj in heap.GetObjectsOfType("System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner"))
            {
                try
                {
                    var stateMachine = obj.ReadObjectField("m_stateMachine");
                    if (!knownStateMachines.ContainsKey(stateMachine.Address))
                    {
                        try
                        {
                            var state = stateMachine.ReadField <int>("<>1__state");
                            if (state >= -1)
                            {
                                ClrObject taskField    = default(ClrObject);
                                var       asyncBuilder = stateMachine.TryGetValueClassField("<>t__builder");
                                if (asyncBuilder.HasValue)
                                {
                                    while (asyncBuilder.HasValue)
                                    {
                                        taskField = asyncBuilder.TryGetObjectField("m_task");
                                        if (!taskField.IsNull)
                                        {
                                            break;
                                        }

                                        asyncBuilder = asyncBuilder.TryGetValueClassField("m_builder");
                                    }
                                }
                                else
                                {
                                    // CLR debugger may not be able to access t__builder, when NGEN assemblies are being used, and the type of the field could be lost.
                                    // Our workaround is to pick up the first Task object referenced by the state machine, which seems to be correct.
                                    // That function works with the raw data structure (like how GC scans the object, so it doesn't depend on symbols.
                                    foreach (ClrObject referencedObject in stateMachine.EnumerateReferences(true))
                                    {
                                        if (!referencedObject.IsNull && referencedObject.Type is object)
                                        {
                                            if (string.Equals(referencedObject.Type.Name, "System.Threading.Tasks.Task", StringComparison.Ordinal) || string.Equals(referencedObject.Type.BaseType?.Name, "System.Threading.Tasks.Task", StringComparison.Ordinal))
                                            {
                                                taskField = referencedObject;
                                                break;
                                            }
                                        }
                                    }
                                }

                                var asyncState = new AsyncStateMachine(state, stateMachine, taskField);
                                allStateMachines.Add(asyncState);
                                knownStateMachines.Add(stateMachine.Address, asyncState);

                                if (stateMachine.Type is object)
                                {
                                    foreach (var method in stateMachine.Type.Methods)
                                    {
                                        if (method.Name == "MoveNext" && method.NativeCode != ulong.MaxValue)
                                        {
                                            asyncState.CodeAddress = method.NativeCode;
                                        }
                                    }
                                }
                            }
                        }
                        catch (Exception ex)
                        {
                            context.Output.WriteLine($"Fail to process state machine {stateMachine.Address:x} Type:'{stateMachine.Type?.Name}' Module:'{stateMachine.Type?.Module?.Name}' Error: {ex.Message}");
                        }
                    }
                }
                catch (Exception ex)
                {
                    context.Output.WriteLine($"Fail to process AsyncStateMachine Runner {obj.Address:x} Error: {ex.Message}");
                }
            }
        }
示例#17
0
        private static void ChainStateMachineBasedOnTaskContinuations(Dictionary <ulong, AsyncStateMachine> knownStateMachines, AsyncStateMachine stateMachine, ClrObject continuationObject)
        {
            var continuationAction = continuationObject.TryGetObjectField("m_action");

            // case 1
            var continuationTarget = continuationAction.TryGetObjectField("_target");

            if (continuationTarget.IsNull)
            {
                // case 2
                continuationTarget = continuationObject.TryGetObjectField("_target");
                if (continuationTarget.IsNull)
                {
                    // case 3
                    continuationTarget = continuationObject.TryGetObjectField("m_task").TryGetObjectField("m_stateObject").TryGetObjectField("_target");
                }
            }

            while (!continuationTarget.IsNull)
            {
                // now get the continuation from the target
                var continuationTargetStateMachine = continuationTarget.TryGetObjectField("m_stateMachine");
                if (!continuationTargetStateMachine.IsNull)
                {
                    AsyncStateMachine targetAsyncState;
                    if (knownStateMachines.TryGetValue(continuationTargetStateMachine.Address, out targetAsyncState) && targetAsyncState != stateMachine)
                    {
                        stateMachine.Next = targetAsyncState;
                        stateMachine.DependentCount++;
                        targetAsyncState.Previous = stateMachine;
                    }

                    break;
                }
                else
                {
                    var nextContinuation = continuationTarget.TryGetObjectField("m_continuation");
                    continuationTarget = nextContinuation.TryGetObjectField("_target");
                }
            }

            var items = continuationObject.TryGetObjectField("_items");

            if (!items.IsNull && items.IsArray && items.ContainsPointers)
            {
                foreach (var promise in items.EnumerateReferences(true))
                {
                    if (!promise.IsNull)
                    {
                        var innerContinuationObject = promise.TryGetObjectField("m_continuationObject");
                        if (!innerContinuationObject.IsNull)
                        {
                            ChainStateMachineBasedOnTaskContinuations(knownStateMachines, stateMachine, innerContinuationObject);
                        }
                        else
                        {
                            ChainStateMachineBasedOnTaskContinuations(knownStateMachines, stateMachine, promise);
                        }
                    }
                }
            }
        }
示例#18
0
        private static void GetAllStateMachines(DebuggerContext context, ClrHeap heap, List <AsyncStateMachine> allStateMachines, Dictionary <ulong, AsyncStateMachine> knownStateMachines)
        {
            foreach (ClrObject obj in heap.GetObjectsOfType("System.Runtime.CompilerServices.AsyncMethodBuilderCore+MoveNextRunner"))
            {
                try
                {
                    ClrObject stateMachine = obj.ReadObjectField("m_stateMachine");
                    if (!knownStateMachines.ContainsKey(stateMachine.Address))
                    {
                        try
                        {
                            var state = stateMachine.ReadField <int>("<>1__state");
                            if (state >= -1)
                            {
                                ClrObject    taskField    = default(ClrObject);
                                ClrValueType?asyncBuilder = stateMachine.TryGetValueClassField("<>t__builder");
                                if (asyncBuilder.HasValue)
                                {
                                    while (asyncBuilder.HasValue)
                                    {
                                        taskField = asyncBuilder.TryGetObjectField("m_task");
                                        if (!taskField.IsNull)
                                        {
                                            break;
                                        }

                                        ClrValueType?nextAsyncBuilder = asyncBuilder.TryGetValueClassField("m_builder");
                                        if (nextAsyncBuilder is null)
                                        {
                                            asyncBuilder = asyncBuilder.TryGetValueClassField("_methodBuilder");
                                        }
                                        else
                                        {
                                            asyncBuilder = nextAsyncBuilder;
                                        }
                                    }
                                }
                                else
                                {
                                    // CLR debugger may not be able to access t__builder, when NGEN assemblies are being used, and the type of the field could be lost.
                                    // Our workaround is to pick up the first Task object referenced by the state machine, which seems to be correct.
                                    // That function works with the raw data structure (like how GC scans the object, so it doesn't depend on symbols.
                                    //
                                    // However, one problem of that is we can pick up tasks from other reference fields of the same structure. So, we go through fields which we have symbols
                                    // and remember references encounted, and we skip them when we go through GC references.
                                    // Note: we can do better by going through other value structures, and extract references from them here, which we can consider when we have a real scenario.
                                    var previousReferences = new Dictionary <ulong, int>();
                                    if (stateMachine.Type?.GetFieldByName("<>t__builder") is not null)
                                    {
                                        foreach (ClrInstanceField field in stateMachine.Type.Fields)
                                        {
                                            if (string.Equals(field.Name, "<>t__builder", StringComparison.Ordinal))
                                            {
                                                break;
                                            }

                                            if (field.IsObjectReference)
                                            {
                                                ClrObject referencedValue = field.ReadObject(stateMachine.Address, interior: false);
                                                if (!referencedValue.IsNull)
                                                {
                                                    if (previousReferences.TryGetValue(referencedValue.Address, out int refCount))
                                                    {
                                                        previousReferences[referencedValue.Address] = refCount + 1;
                                                    }
                                                    else
                                                    {
                                                        previousReferences[referencedValue.Address] = 1;
                                                    }
                                                }
                                            }
                                        }
                                    }

                                    foreach (ClrObject referencedObject in stateMachine.EnumerateReferences(true))
                                    {
                                        if (!referencedObject.IsNull)
                                        {
                                            if (previousReferences.TryGetValue(referencedObject.Address, out int refCount) && refCount > 0)
                                            {
                                                if (refCount == 1)
                                                {
                                                    previousReferences.Remove(referencedObject.Address);
                                                }
                                                else
                                                {
                                                    previousReferences[referencedObject.Address] = refCount - 1;
                                                }

                                                continue;
                                            }
                                            else if (previousReferences.Count > 0)
                                            {
                                                continue;
                                            }

                                            if (referencedObject.Type is object &&
                                                (string.Equals(referencedObject.Type.Name, "System.Threading.Tasks.Task", StringComparison.Ordinal) || string.Equals(referencedObject.Type.BaseType?.Name, "System.Threading.Tasks.Task", StringComparison.Ordinal)))
                                            {
                                                taskField = referencedObject;
                                                break;
                                            }
                                        }
                                    }
                                }

                                var asyncState = new AsyncStateMachine(state, stateMachine, taskField);
                                allStateMachines.Add(asyncState);
                                knownStateMachines.Add(stateMachine.Address, asyncState);

                                if (stateMachine.Type is object)
                                {
                                    foreach (ClrMethod?method in stateMachine.Type.Methods)
                                    {
                                        if (method.Name == "MoveNext" && method.NativeCode != ulong.MaxValue)
                                        {
                                            asyncState.CodeAddress = method.NativeCode;
                                        }
                                    }
                                }
                            }
                        }
#pragma warning disable CA1031 // Do not catch general exception types
                        catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
                        {
                            context.Output.WriteLine($"Fail to process state machine {stateMachine.Address:x} Type:'{stateMachine.Type?.Name}' Module:'{stateMachine.Type?.Module?.Name}' Error: {ex.Message}");
                        }
                    }
                }
#pragma warning disable CA1031 // Do not catch general exception types
                catch (Exception ex)
#pragma warning restore CA1031 // Do not catch general exception types
                {
                    context.Output.WriteLine($"Fail to process AsyncStateMachine Runner {obj.Address:x} Error: {ex.Message}");
                }
            }
        }