public void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine stateMachine) { }
public void Start<TStateMachine>(ref TStateMachine stateMachine) where TStateMachine : System.Runtime.CompilerServices.IAsyncStateMachine { }
}
+ public readonly struct ConfiguredAsyncDisposable
+ {
+ private readonly object _dummy;
+ public System.Runtime.CompilerServices.ConfiguredValueTaskAwaitable DisposeAsync() { throw null; }
+ }
public readonly struct ConfiguredCancelableAsyncEnumerable<T>
{
private readonly object _dummy;
}
public static partial class TaskExtensions
{
+ public static System.Runtime.CompilerServices.ConfiguredAsyncDisposable ConfigureAwait(this System.IAsyncDisposable source, bool continueOnCapturedContext) { throw null; }
public static System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable<T> ConfigureAwait<T>(this System.Collections.Generic.IAsyncEnumerable<T> source, bool continueOnCapturedContext) { throw null; }
public static System.Runtime.CompilerServices.ConfiguredCancelableAsyncEnumerable<T> WithCancellation<T>(this System.Collections.Generic.IAsyncEnumerable<T> source, CancellationToken cancellationToken) { throw null; }
public static System.Threading.Tasks.Task Unwrap(this System.Threading.Tasks.Task<System.Threading.Tasks.Task> task) { throw null; }
--- /dev/null
+// 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.Threading.Tasks;
+using System.Threading.Tasks.Sources;
+using Xunit;
+
+namespace System.Runtime.CompilerServices.Tests
+{
+ public class ConfiguredAsyncDisposableTests
+ {
+ [Fact]
+ public void Default_GetAsyncEnumerator_Throws()
+ {
+ ConfiguredAsyncDisposable d = default;
+ Assert.Throws<NullReferenceException>(() => d.DisposeAsync());
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void DisposeAsync_InvokesUnderlyingDisposeAsync(bool continueOnCapturedContext)
+ {
+ int invokeCount = 0;
+ var tcs = new TaskCompletionSource<int>();
+ var vt = new ValueTask(tcs.Task);
+
+ var d = new CustomAsyncDisposable(() =>
+ {
+ invokeCount++;
+ return vt;
+ });
+
+ Assert.Equal(vt.ConfigureAwait(continueOnCapturedContext), d.ConfigureAwait(continueOnCapturedContext).DisposeAsync());
+ Assert.Equal(1, invokeCount);
+ }
+
+ [Theory]
+ [InlineData(false)]
+ [InlineData(true)]
+ public void DisposeAsync_ContinuesOnCapturedContextIfExpected(bool continueOnCapturedContext)
+ {
+ var d = new TrackingAsyncDisposable();
+ d.ConfigureAwait(continueOnCapturedContext).DisposeAsync().GetAwaiter().UnsafeOnCompleted(() => { });
+ Assert.Equal(
+ continueOnCapturedContext ? ValueTaskSourceOnCompletedFlags.UseSchedulingContext : ValueTaskSourceOnCompletedFlags.None,
+ d.Flags);
+ }
+
+ private sealed class CustomAsyncDisposable : IAsyncDisposable
+ {
+ private readonly Func<ValueTask> _action;
+
+ public CustomAsyncDisposable(Func<ValueTask> action) => _action = action;
+
+ public ValueTask DisposeAsync() => _action();
+ }
+
+ private sealed class TrackingAsyncDisposable : IAsyncDisposable, IValueTaskSource
+ {
+ public ValueTaskSourceOnCompletedFlags Flags;
+
+ public ValueTask DisposeAsync() => new ValueTask(this, 0);
+
+ public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) => Flags = flags;
+ public ValueTaskSourceStatus GetStatus(short token) => ValueTaskSourceStatus.Pending;
+ public bool GetResult(short token) => throw new NotImplementedException();
+ void IValueTaskSource.GetResult(short token) => throw new NotImplementedException();
+ }
+ }
+}
Assert.Equal(token1, enumerable.CancellationToken);
}
- private sealed class TrackFlagsAsyncEnumerable : IAsyncEnumerable<int>, IAsyncEnumerator<int>, IValueTaskSource<bool>, IValueTaskSource
+ private sealed class TrackFlagsAsyncEnumerable : IAsyncEnumerable<int>
{
public ValueTaskSourceOnCompletedFlags Flags;
public CancellationToken CancellationToken;
public IAsyncEnumerator<int> GetAsyncEnumerator(CancellationToken cancellationToken = default)
{
CancellationToken = cancellationToken;
- return this;
+ return new Enumerator(this);
}
- public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(this, 0);
- public int Current => throw new NotImplementedException();
- public ValueTask DisposeAsync() => new ValueTask(this, 0);
+ private sealed class Enumerator : IAsyncEnumerator<int>, IValueTaskSource<bool>, IValueTaskSource
+ {
+ private readonly TrackFlagsAsyncEnumerable _enumerable;
+
+ public Enumerator(TrackFlagsAsyncEnumerable enumerable) => _enumerable = enumerable;
- public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) => Flags = flags;
- public ValueTaskSourceStatus GetStatus(short token) => ValueTaskSourceStatus.Pending;
- public bool GetResult(short token) => throw new NotImplementedException();
- void IValueTaskSource.GetResult(short token) => throw new NotImplementedException();
+ public ValueTask<bool> MoveNextAsync() => new ValueTask<bool>(this, 0);
+ public int Current => throw new NotImplementedException();
+ public ValueTask DisposeAsync() => new ValueTask(this, 0);
+
+ public void OnCompleted(Action<object> continuation, object state, short token, ValueTaskSourceOnCompletedFlags flags) => _enumerable.Flags = flags;
+ public ValueTaskSourceStatus GetStatus(short token) => ValueTaskSourceStatus.Pending;
+ public bool GetResult(short token) => throw new NotImplementedException();
+ void IValueTaskSource.GetResult(short token) => throw new NotImplementedException();
+ }
}
private sealed class EnumerableWithDelayToAsyncEnumerable<T> : IAsyncEnumerable<T>, IAsyncEnumerator<T>
<Compile Include="Task\TaskCanceledExceptionTests.netcoreapp.cs" />
<Compile Include="Task\TaskStatusTest.netcoreapp.cs" />
<Compile Include="System.Runtime.CompilerServices\AsyncTaskMethodBuilderTests.netcoreapp.cs" />
+ <Compile Include="System.Runtime.CompilerServices\ConfiguredAsyncDisposable.netcoreapp.cs" />
<Compile Include="System.Runtime.CompilerServices\ConfiguredCancelableAsyncEnumerableTests.netcoreapp.cs" />
<Compile Include="$(CommonTestPath)\System\Diagnostics\Tracing\TestEventListener.cs">
<Link>Common\System\Diagnostics\Tracing\TestEventListener.cs</Link>