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); }
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); }
[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); }
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); } } }
/// <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); } }