public async Task TestSequentialEnumeratorAsync() { var start = MAX_ITEMS; var completionState = new Int32[start]; var r = new Random(); MoveNextAsyncDelegate <Int32> moveNext = async() => { var decremented = Interlocked.Decrement(ref start); await Task.Delay(r.Next(100, 500)); return(decremented >= 0, MAX_ITEMS - decremented - 1); }; var enumerable = AsyncEnumerationFactory.CreateSequentialEnumerable(() => AsyncEnumerationFactory.CreateSequentialStartInfo( moveNext, null ), DefaultAsyncProvider.Instance); Func <Int32, Task> callback = async idx => { await Task.Delay(r.Next(100, 900)); Assert.IsTrue(completionState.Take(idx).All(s => s == 1)); Interlocked.Increment(ref completionState[idx]); }; var itemsEncountered = await enumerable.EnumerateAsync(callback); Assert.AreEqual(itemsEncountered, completionState.Length); Assert.IsTrue(completionState.All(s => s == 1)); }
internal static SequentialEnumeratorCurrentInfo <T> GetInstance <T>( MoveNextAsyncDelegate <T> moveNext, EnumerationEndedDelegate dispose ) { return((SequentialEnumeratorCurrentInfo <T>)GetFactory(typeof(T))?.Invoke(moveNext, dispose) ?? new SequentialEnumeratorCurrentInfoWithObject <T>(moveNext, dispose)); }
/// <summary> /// Initializes a new <see cref="SequentialEnumerationStartInfo{T}"/> with given callbacks. /// </summary> /// <param name="moveNext">The callback to fetch next item.</param> /// <param name="dispose">The optional callback to dispose enumerator. May be <c>null</c>.</param> /// <remarks> /// If <paramref name="moveNext"/> is <c>null</c>, then enumeration ends immediately. /// </remarks> /// <seealso cref="AsyncEnumerationFactory.CreateSequentialStartInfo"/> public SequentialEnumerationStartInfo( MoveNextAsyncDelegate <T> moveNext, EnumerationEndedDelegate dispose ) { this.MoveNext = moveNext; this.Dispose = dispose; }
public Task TestSequentialEnumeratorCompletelySync() { var start = MAX_ITEMS; var completionState = new Int32[start]; var r = new Random(); MoveNextAsyncDelegate <Int32> moveNext = () => { var decremented = Interlocked.Decrement(ref start); return(new ValueTask <(Boolean, Int32)>((decremented >= 0, MAX_ITEMS - decremented - 1))); };
public CurrentInfo( T current, MoveNextAsyncDelegate <T> moveNext, DisposeAsyncDelegate disposeDelegate ) { this.MoveNext = moveNext; this.Current = current ?? throw new ArgumentNullException(nameof(current)); this.Dispose = disposeDelegate; }
/// <summary> /// Creates a new instance of <see cref="IAsyncEnumerator{T}"/> which fetches one item at a time using given callback. /// </summary> /// <typeparam name="T">The type of items being enumerated.</typeparam> /// <param name="moveNext">The callback for potentially asynchronously fetching next item.</param> /// <param name="dispose">The callback to dispose enumerator.</param> /// <returns>A new instance of <see cref="IAsyncEnumerator{T}"/> which behaves like <paramref name="moveNext"/> and <paramref name="dispose"/> specify.</returns> /// <remarks> /// The returned <see cref="IAsyncEnumerator{T}"/> will have guard code to prevent concurrent invocation. /// </remarks> public static IAsyncEnumerator <T> CreateSequentialEnumerator <T>( MoveNextAsyncDelegate <T> moveNext, EnumerationEndedDelegate dispose ) => new AsyncEnumerator <T>(SequentialCurrentInfoFactory.GetInstance(moveNext, dispose));
/// <summary> /// Helper method to invoke constructor of <see cref="SequentialEnumerationStartInfo{T}"/> without explicitly specifying generic type arguments. /// </summary> /// <typeparam name="T">The type of items being enumerated.</typeparam> /// <param name="moveNext">The callback for potentially asynchronously fetching next item.</param> /// <param name="dispose">The callback to dispose enumerator.</param> /// <returns>A new <see cref="SequentialEnumerationStartInfo{T}"/>.</returns> /// <seealso cref="SequentialEnumerationStartInfo{T}.SequentialEnumerationStartInfo(MoveNextAsyncDelegate{T}, EnumerationEndedDelegate)"/> public static SequentialEnumerationStartInfo <T> CreateSequentialStartInfo <T>( MoveNextAsyncDelegate <T> moveNext, EnumerationEndedDelegate dispose ) => new SequentialEnumerationStartInfo <T>(moveNext, dispose);