diff options
Diffstat (limited to 'src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs')
-rw-r--r-- | src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs | 41 |
1 files changed, 39 insertions, 2 deletions
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs index c45ef2484..68fd5ab8d 100644 --- a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs +++ b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/YieldAwaitable.cs @@ -47,6 +47,9 @@ namespace System.Runtime.CompilerServices /// <summary>Provides an awaiter that switches into a target environment.</summary> /// <remarks>This type is intended for compiler use only.</remarks> public readonly struct YieldAwaiter : ICriticalNotifyCompletion +#if CORECLR + , IStateMachineBoxAwareAwaiter +#endif { /// <summary>Gets whether a yield is not required.</summary> /// <remarks>This property is intended for compiler user rather than use directly in code.</remarks> @@ -110,11 +113,46 @@ namespace System.Runtime.CompilerServices // We're targeting a custom scheduler, so queue a task. else { - Task.Factory.StartNew(continuation, default(CancellationToken), TaskCreationOptions.PreferFairness, scheduler); + Task.Factory.StartNew(continuation, default, TaskCreationOptions.PreferFairness, scheduler); } } } +#if CORECLR + 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); + } + } + } +#endif + private static Action OutputCorrelationEtwEvent(Action continuation) { #if CORERT @@ -153,7 +191,6 @@ namespace System.Runtime.CompilerServices private static readonly WaitCallback s_waitCallbackRunAction = RunAction; /// <summary>SendOrPostCallback that invokes the Action supplied as object state.</summary> private static readonly SendOrPostCallback s_sendOrPostCallbackRunAction = RunAction; - /// <summary>Runs an Action delegate provided as state.</summary> /// <param name="state">The Action delegate to invoke.</param> private static void RunAction(object state) { ((Action)state)(); } |