void IStateMachineBoxAwareAwaiter.AwaitUnsafeOnCompleted(IAsyncStateMachineBox box)
            {
                Debug.Assert(box != null);

                // If tracing is enabled, delegate the Action-based implementation.
                if (TplEtwProvider.Log.IsEnabled())
                {
                    QueueContinuation(box.MoveNextAction, flowContext: false);
                    return;
                }

                // Otherwise, this is the same logic as in QueueContinuation, except using
                // an IAsyncStateMachineBox instead of an Action, and only for flowContext:false.

                SynchronizationContext syncCtx = SynchronizationContext.Current;

                if (syncCtx != null && syncCtx.GetType() != typeof(SynchronizationContext))
                {
                    syncCtx.Post(s => ((IAsyncStateMachineBox)s).MoveNext(), box);
                }
                else
                {
                    TaskScheduler scheduler = TaskScheduler.Current;
                    if (scheduler == TaskScheduler.Default)
                    {
                        ThreadPool.UnsafeQueueUserWorkItem(s => ((IAsyncStateMachineBox)s).MoveNext(), box);
                    }
                    else
                    {
                        Task.Factory.StartNew(s => ((IAsyncStateMachineBox)s).MoveNext(), box, default, TaskCreationOptions.PreferFairness, scheduler);
        internal static void AwaitUnsafeOnCompleted <TAwaiter, TStateMachine>(
            ref TAwaiter awaiter, ref TStateMachine stateMachine, [NotNull] ref StateMachineBox?boxRef)
            where TAwaiter : ICriticalNotifyCompletion
            where TStateMachine : IAsyncStateMachine
        {
            IAsyncStateMachineBox box = GetStateMachineBox(ref stateMachine, ref boxRef);

            AsyncTaskMethodBuilder <VoidTaskResult> .AwaitUnsafeOnCompleted(ref awaiter, box);
        }
Esempio n. 3
0
        internal static void AwaitUnsafeOnCompleted <TAwaiter, TStateMachine>(
            ref TAwaiter awaiter, ref TStateMachine stateMachine, [NotNull] ref Task <TResult>?taskField)
            where TAwaiter : ICriticalNotifyCompletion
            where TStateMachine : IAsyncStateMachine
        {
            IAsyncStateMachineBox box = GetStateMachineBox(ref stateMachine, ref taskField);

            AwaitUnsafeOnCompleted(ref awaiter, box);
        }
Esempio n. 4
0
        [MethodImpl(MethodImplOptions.AggressiveOptimization)] // workaround boxing allocations in Tier0: https://github.com/dotnet/runtime/issues/9120
        internal static void AwaitUnsafeOnCompleted <TAwaiter>(
            ref TAwaiter awaiter, IAsyncStateMachineBox box)
            where TAwaiter : ICriticalNotifyCompletion
        {
            // The null tests here ensure that the jit can optimize away the interface
            // tests when TAwaiter is a ref type.

            if ((null != (object?)default(TAwaiter)) && (awaiter is ITaskAwaiter))
            {
                ref TaskAwaiter ta = ref Unsafe.As <TAwaiter, TaskAwaiter>(ref awaiter); // relies on TaskAwaiter/TaskAwaiter<T> having the same layout
                TaskAwaiter.UnsafeOnCompletedInternal(ta.m_task, box, continueOnCapturedContext: true);
            }
Esempio n. 5
0
 public void IncompleteAsyncMethod(IAsyncStateMachineBox stateMachineBox)
 {
     System.Diagnostics.Debug.Assert(stateMachineBox != null);
     if (IsEnabled(EventLevel.Warning, Keywords.AsyncMethod))
     {
         IAsyncStateMachine stateMachine = stateMachineBox.GetStateMachineObject();
         if (stateMachine != null)
         {
             string description = AsyncMethodBuilderCore.GetAsyncStateMachineDescription(stateMachine);
             IncompleteAsyncMethod(description);
         }
     }
 }
Esempio n. 6
0
        /// <summary>Schedules the continuation onto the <see cref="System.Threading.Tasks.Task"/> associated with this <see cref="TaskAwaiter"/>.</summary>
        /// <param name="task">The task being awaited.</param>
        /// <param name="stateMachineBox">The box to invoke when the await operation completes.</param>
        /// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param>
        internal static void UnsafeOnCompletedInternal(Task task, IAsyncStateMachineBox stateMachineBox, bool continueOnCapturedContext)
        {
            Debug.Assert(stateMachineBox != null);

            // If TaskWait* ETW events are enabled, trace a beginning event for this await
            // and set up an ending event to be traced when the asynchronous await completes.
            if (TplEventSource.Log.IsEnabled() || Task.s_asyncDebuggingEnabled)
            {
                task.SetContinuationForAwait(OutputWaitEtwEvents(task, stateMachineBox.MoveNextAction), continueOnCapturedContext, flowExecutionContext: false);
            }
            else
            {
                task.UnsafeSetContinuationForAwait(stateMachineBox, continueOnCapturedContext);
            }
        }