Add ConfigureAwait extension method for IAsyncEnumerable
authorStephen Toub <stoub@microsoft.com>
Fri, 26 Oct 2018 04:19:26 +0000 (21:19 -0700)
committerStephen Toub <stoub@microsoft.com>
Fri, 26 Oct 2018 04:28:04 +0000 (21:28 -0700)
Commit migrated from https://github.com/dotnet/coreclr/commit/9e16ad51dd0f5e77b2dbaa6300dc2da1aafe21f3

src/libraries/System.Private.CoreLib/src/System.Private.CoreLib.Shared.projitems
src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConfiguredAsyncEnumerable.cs [new file with mode: 0644]
src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/TaskExtensions.cs

index 52e9a5a..078444f 100644 (file)
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CompilationRelaxationsAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CompilerGeneratedAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CompilerGlobalScopeAttribute.cs" />
+    <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ConfiguredAsyncEnumerable.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ConfiguredValueTaskAwaitable.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\CustomConstantAttribute.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\DateTimeConstantAttribute.cs" />
diff --git a/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConfiguredAsyncEnumerable.cs b/src/libraries/System.Private.CoreLib/src/System/Runtime/CompilerServices/ConfiguredAsyncEnumerable.cs
new file mode 100644 (file)
index 0000000..57fd481
--- /dev/null
@@ -0,0 +1,47 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+using System.Threading.Tasks;
+using System.Threading.Tasks.Sources;
+
+namespace System.Runtime.CompilerServices
+{
+    [StructLayout(LayoutKind.Auto)]
+    public readonly struct ConfiguredAsyncEnumerable<T>
+    {
+        private readonly IAsyncEnumerable<T> _enumerable;
+        private readonly bool _continueOnCapturedContext;
+
+        internal ConfiguredAsyncEnumerable(IAsyncEnumerable<T> enumerable, bool continueOnCapturedContext)
+        {
+            _enumerable = enumerable;
+            _continueOnCapturedContext = continueOnCapturedContext;
+        }
+
+        public Enumerator GetAsyncEnumerator() =>
+            new Enumerator(_enumerable.GetAsyncEnumerator(), _continueOnCapturedContext);
+
+        public readonly struct Enumerator
+        {
+            private readonly IAsyncEnumerator<T> _enumerator;
+            private readonly bool _continueOnCapturedContext;
+
+            internal Enumerator(IAsyncEnumerator<T> enumerator, bool continueOnCapturedContext)
+            {
+                _enumerator = enumerator;
+                _continueOnCapturedContext = continueOnCapturedContext;
+            }
+
+            public ConfiguredValueTaskAwaitable<bool> MoveNextAsync() =>
+                _enumerator.MoveNextAsync().ConfigureAwait(_continueOnCapturedContext);
+
+            public T Current => _enumerator.Current;
+
+            public ConfiguredValueTaskAwaitable DisposeAsync() =>
+                _enumerator.DisposeAsync().ConfigureAwait(_continueOnCapturedContext);
+        }
+    }
+}
index 97f2013..a07033d 100644 (file)
@@ -2,6 +2,9 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+
 namespace System.Threading.Tasks
 {
     /// <summary>Provides a set of static methods for working with specific kinds of <see cref="Task"/> instances.</summary>
@@ -44,5 +47,14 @@ namespace System.Threading.Tasks
                 task.Result ??
                 Task.FromCanceled<TResult>(new CancellationToken(true));
         }
+
+        /// <summary>Configures how awaits on the tasks returned from an async iteration will be performed.</summary>
+        /// <typeparam name="T">The type of the objects being iterated.</typeparam>
+        /// <param name="source">The source enumerable being iterated.</param>
+        /// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param>
+        /// <returns>The configured enumerable.</returns>
+        public static ConfiguredAsyncEnumerable<T> ConfigureAwait<T>(
+            this IAsyncEnumerable<T> source, bool continueOnCapturedContext) =>
+            new ConfiguredAsyncEnumerable<T>(source, continueOnCapturedContext);
     }
 }