Implement IAsyncDisposable.ConfigureAwait (#22160)
authorStephen Toub <stoub@microsoft.com>
Thu, 24 Jan 2019 01:51:34 +0000 (20:51 -0500)
committerGitHub <noreply@github.com>
Thu, 24 Jan 2019 01:51:34 +0000 (20:51 -0500)
src/System.Private.CoreLib/shared/System.Private.CoreLib.Shared.projitems
src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredAsyncDisposable.cs [new file with mode: 0644]
src/System.Private.CoreLib/shared/System/Threading/Tasks/TaskExtensions.cs

index 9ba6e27..954f2ef 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\ConfiguredAsyncDisposable.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ConfiguredCancelableAsyncEnumerable.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ConfiguredValueTaskAwaitable.cs" />
     <Compile Include="$(MSBuildThisFileDirectory)System\Runtime\CompilerServices\ContractHelper.cs" />
diff --git a/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredAsyncDisposable.cs b/src/System.Private.CoreLib/shared/System/Runtime/CompilerServices/ConfiguredAsyncDisposable.cs
new file mode 100644 (file)
index 0000000..aa5e882
--- /dev/null
@@ -0,0 +1,27 @@
+// 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.Runtime.InteropServices;
+
+namespace System.Runtime.CompilerServices
+{
+    /// <summary>Provides a type that can be used to configure how awaits on an <see cref="IAsyncDisposable"/> are performed.</summary>
+    [StructLayout(LayoutKind.Auto)]
+    public readonly struct ConfiguredAsyncDisposable
+    {
+        private readonly IAsyncDisposable _source;
+        private readonly bool _continueOnCapturedContext;
+
+        internal ConfiguredAsyncDisposable(IAsyncDisposable source, bool continueOnCapturedContext)
+        {
+            _source = source;
+            _continueOnCapturedContext = continueOnCapturedContext;
+        }
+
+        public ConfiguredValueTaskAwaitable DisposeAsync() =>
+            // as with other "configured" awaitable-related type in CompilerServices, we don't null check to defend against
+            // misuse like `default(ConfiguredAsyncDisposable).DisposeAsync()`, which will null ref by design.
+            _source.DisposeAsync().ConfigureAwait(_continueOnCapturedContext);
+    }
+}
index 9192b14..75b4b0a 100644 (file)
@@ -48,6 +48,13 @@ namespace System.Threading.Tasks
                 Task.FromCanceled<TResult>(new CancellationToken(true));
         }
 
+        /// <summary>Configures how awaits on the tasks returned from an async disposable will be performed.</summary>
+        /// <param name="source">The source async disposable.</param>
+        /// <param name="continueOnCapturedContext">Whether to capture and marshal back to the current context.</param>
+        /// <returns>The configured async disposable.</returns>
+        public static ConfiguredAsyncDisposable ConfigureAwait(this IAsyncDisposable source, bool continueOnCapturedContext) =>
+            new ConfiguredAsyncDisposable(source, continueOnCapturedContext);
+
         /// <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>