コード例 #1
0
        public void AwaitOnCompleted <TAwaiter, TStateMachine>(ref TAwaiter awaiter, ref TStateMachine stateMachine)
            where TAwaiter : INotifyCompletion where TStateMachine : IAsyncStateMachine
        {
            Console.WriteLine("In AwaitOnCompleted");
            var executionContext = ExecutionContext.Capture();
            var moveNextRunner   = new MoveNextRunner(stateMachine, executionContext);

            awaiter.OnCompleted(moveNextRunner.MoveNextSafe);
        }
コード例 #2
0
        public void AwaitUnsafeOnCompleted <TAwaiter, TStateMachine>(ref TAwaiter awaiter,
                                                                     ref TStateMachine stateMachine) where TAwaiter : ICriticalNotifyCompletion
            where TStateMachine : IAsyncStateMachine
        {
            Console.WriteLine("In AwaitUnsafeOnCompleted");
            var moveNextRunner = new MoveNextRunner(stateMachine);

            awaiter.UnsafeOnCompleted(moveNextRunner.MoveNextUnsafe);
        }
コード例 #3
0
        internal static Action TryGetStateMachineForDebugger(Action action)
        {
            Object         target = action.Target;
            MoveNextRunner runner = target as MoveNextRunner;

            if (runner != null)
            {
                return(runner.m_stateMachine.MoveNext);
            }
            return(action);
        }
コード例 #4
0
        internal Action GetCompletionAction <TMethodBuilder, TStateMachine>(ref TMethodBuilder builder, ref TStateMachine stateMachine) where TMethodBuilder : IAsyncMethodBuilder where TStateMachine : IAsyncStateMachine
        {
            var context        = ExecutionContextLightup.Instance.Capture();
            var moveNextRunner = new MoveNextRunner(context);
            var result         = new Action(moveNextRunner.Run);

            if (m_stateMachine == null)
            {
                builder.PreBoxInitialization();
                m_stateMachine = stateMachine;
                m_stateMachine.SetStateMachine(m_stateMachine);
            }
            moveNextRunner.m_stateMachine = m_stateMachine;
            return(result);
        }
コード例 #5
0
        internal Action GetCompletionAction <TMethodBuilder, TStateMachine>(ref TMethodBuilder builder, ref TStateMachine stateMachine)
            where TMethodBuilder : IAsyncMethodBuilder
            where TStateMachine : IAsyncStateMachine
        {
            var    moveNextRunner = new MoveNextRunner(ExecutionContext.Capture());
            Action action         = moveNextRunner.Run;

            if (this.stateMachine == null)
            {
                builder.PreBoxInitialization();
                this.stateMachine = stateMachine;
                this.stateMachine.SetStateMachine(this.stateMachine);
            }
            moveNextRunner.StateMachine = this.stateMachine;
            return(action);
        }
コード例 #6
0
        /// <summary>
        /// Gets the <see cref="Action"/> to use with an awaiter's <see cref="INotifyCompletion.OnCompleted"/> or
        /// <see cref="ICriticalNotifyCompletion.UnsafeOnCompleted"/> method. On first invocation, the supplied state
        /// machine will be boxed.
        /// </summary>
        /// <typeparam name="TMethodBuilder">Specifies the type of the method builder used.</typeparam>
        /// <typeparam name="TStateMachine">Specifies the type of the state machine used.</typeparam>
        /// <param name="builder">The builder.</param>
        /// <param name="stateMachine">The state machine.</param>
        /// <returns>An <see cref="Action"/> to provide to the awaiter.</returns>
        internal Action GetCompletionAction <TMethodBuilder, TStateMachine>(ref TMethodBuilder builder, ref TStateMachine stateMachine)
            where TMethodBuilder : IAsyncMethodBuilder
            where TStateMachine : IAsyncStateMachine
        {
            ExecutionContext context        = ExecutionContext.Capture();
            MoveNextRunner   moveNextRunner = new MoveNextRunner(context);
            Action           result         = moveNextRunner.Run;

            if (_stateMachine == null)
            {
                builder.PreBoxInitialization(ref stateMachine);
                _stateMachine = stateMachine;
                _stateMachine.SetStateMachine(_stateMachine);
            }

            moveNextRunner._stateMachine = _stateMachine;
            return(result);
        }
コード例 #7
0
        /// <summary>
        /// Gets the <see cref="Action"/> to use with an awaiter's <see cref="INotifyCompletion.OnCompleted"/> or
        /// <see cref="ICriticalNotifyCompletion.UnsafeOnCompleted"/> method. On first invocation, the supplied state
        /// machine will be boxed.
        /// </summary>
        /// <typeparam name="TMethodBuilder">Specifies the type of the method builder used.</typeparam>
        /// <typeparam name="TStateMachine">Specifies the type of the state machine used.</typeparam>
        /// <param name="builder">The builder.</param>
        /// <param name="stateMachine">The state machine.</param>
        /// <returns>An <see cref="Action"/> to provide to the awaiter.</returns>
#if !SILVERLIGHT
        //// [SecuritySafeCritical]
#endif
        internal Action GetCompletionAction<TMethodBuilder, TStateMachine>(ref TMethodBuilder builder, ref TStateMachine stateMachine)
            where TMethodBuilder : IAsyncMethodBuilder
            where TStateMachine : IAsyncStateMachine
        {
            Debug.Assert(builder != null, "Expected valid builder");
            Debug.Assert(stateMachine != null, "Expected valid state machine reference");

            // The builder needs to flow ExecutionContext, so capture it.
            var capturedContext = ExecutionContextLightup.Instance.Capture();

            MoveNextRunner runner = new MoveNextRunner(capturedContext);
            Action action = new Action(runner.Run);

            // If this is our first await, such that we've not yet boxed the state machine, do so now.
            if (_stateMachine == null)
            {
                // This is our first await, and we're not boxed yet. First performance any work that must affect both
                // the non-boxed and boxed builders.
                builder.PreBoxInitialization();

                // Box the state machine, then tell the boxed instance to call back into its own builder, so we can
                // cache the boxed reference.
                Debug.Assert(!object.ReferenceEquals((object)stateMachine, (object)stateMachine), "Expected an unboxed state machine reference");
                _stateMachine = stateMachine;
                _stateMachine.SetStateMachine(_stateMachine);
            }

            Debug.Assert(runner._stateMachine == null, "The runner's state machine should not yet have been populated.");
            Debug.Assert(_stateMachine != null, "The builder's state machine field should have been initialized.");

            // Now that we have the state machine, store it into the runner that the action delegate points to. And
            // return the action.
            //
            // Only after this line is the Action delegate usable.
            runner._stateMachine = _stateMachine;
            return action;
        }
コード例 #8
0
        private static unsafe Action GetCompletionActionHelper(
            ref Action cachedMoveNextAction,
            ref byte stateMachineAddress,
            EETypePtr stateMachineType,
            Task taskIfDebuggingEnabled)
        {
            // Alert a listening debugger that we can't make forward progress unless it slips threads.
            // If we don't do this, and a method that uses "await foo;" is invoked through funceval,
            // we could end up hooking up a callback to push forward the async method's state machine,
            // the debugger would then abort the funceval after it takes too long, and then continuing
            // execution could result in another callback being hooked up.  At that point we have
            // multiple callbacks registered to push the state machine, which could result in bad behavior.
            //Debugger.NotifyOfCrossThreadDependency();

            MoveNextRunner runner;

            if (cachedMoveNextAction != null)
            {
                Debug.Assert(cachedMoveNextAction.Target is MoveNextRunner);
                runner = (MoveNextRunner)cachedMoveNextAction.Target;
                runner.m_executionContext = ExecutionContext.Capture();
                return(cachedMoveNextAction);
            }

            runner = new MoveNextRunner();
            runner.m_executionContext = ExecutionContext.Capture();
            cachedMoveNextAction      = runner.CallMoveNext;

            if (taskIfDebuggingEnabled != null)
            {
                runner.m_task = taskIfDebuggingEnabled;

                if (DebuggerSupport.LoggingOn)
                {
                    IntPtr eeType = stateMachineType.RawValue;
                    DebuggerSupport.TraceOperationCreation(CausalityTraceLevel.Required, taskIfDebuggingEnabled, "Async: " + eeType.ToString("x"), 0);
                }
                DebuggerSupport.AddToActiveTasks(taskIfDebuggingEnabled);
            }

            //
            // If the state machine is a value type, we need to box it now.
            //
            IAsyncStateMachine boxedStateMachine;

            if (stateMachineType.IsValueType)
            {
                object boxed = RuntimeImports.RhBox(stateMachineType, ref stateMachineAddress);
                Debug.Assert(boxed is IAsyncStateMachine);
                boxedStateMachine = Unsafe.As <IAsyncStateMachine>(boxed);
            }
            else
            {
                boxedStateMachine = Unsafe.As <byte, IAsyncStateMachine>(ref stateMachineAddress);
            }

            runner.m_stateMachine = boxedStateMachine;

#if DEBUG
            //
            // In debug builds, we'll go ahead and call SetStateMachine, even though all of our initialization is done.
            // This way we'll keep forcing state machine implementations to keep the behavior needed by the CLR.
            //
            boxedStateMachine.SetStateMachine(boxedStateMachine);
#endif

            // All done!
            return(cachedMoveNextAction);
        }