/// <summary>
 /// Invokes an asynchronous action on each item in the collection in parallel
 /// </summary>
 /// <typeparam name="T">The type of an item</typeparam>
 /// <param name="enumerator">The collection of items to perform actions on</param>
 /// <param name="asyncItemAction">An asynchronous action to perform on the item</param>
 /// <param name="cancellationToken">Cancellation token</param>
 /// <exception cref="ParallelForEachException">Wraps any exception(s) that occurred inside <paramref name="asyncItemAction"/></exception>
 /// <exception cref="OperationCanceledException">Thrown when the loop is canceled with <paramref name="cancellationToken"/></exception>
 public static Task ParallelForEachAsync <T>(
     this IAsyncEnumerator <T> enumerator,
     Func <T, Task> asyncItemAction,
     CancellationToken cancellationToken = default)
 => enumerator.ParallelForEachAsync(
     (item, index) => asyncItemAction(item),
     /*maxDegreeOfParallelism:*/ 0,
     /*breakLoopOnException:*/ false,
     /*gracefulBreak:*/ true,
     cancellationToken);
 /// <summary>
 /// Invokes an asynchronous action on each item in the collection in parallel
 /// </summary>
 /// <typeparam name="T">The type of an item</typeparam>
 /// <param name="enumerator">The collection of items to perform actions on</param>
 /// <param name="asyncItemAction">An asynchronous action to perform on the item, where first argument is the item and second argument is item's index in the collection</param>
 /// <param name="maxDegreeOfParallelism">Maximum items to schedule processing in parallel. The actual concurrency level depends on TPL settings. Set to 0 to choose a default value based on processor count.</param>
 /// <param name="breakLoopOnException">Set to True to stop processing items when first exception occurs. The result <see cref="AggregateException"/> might contain several exceptions though when faulty tasks finish at the same time.</param>
 /// <param name="cancellationToken">Cancellation token</param>
 /// <exception cref="ParallelForEachException">Wraps any exception(s) that occurred inside <paramref name="asyncItemAction"/></exception>
 /// <exception cref="OperationCanceledException">Thrown when the loop is canceled with <paramref name="cancellationToken"/></exception>
 public static Task ParallelForEachAsync <T>(
     this IAsyncEnumerator <T> enumerator,
     Func <T, long, Task> asyncItemAction,
     int maxDegreeOfParallelism,
     bool breakLoopOnException,
     CancellationToken cancellationToken = default)
 => enumerator.ParallelForEachAsync(
     asyncItemAction,
     maxDegreeOfParallelism,
     breakLoopOnException,
     /*gracefulBreak:*/ true,
     cancellationToken);
 /// <summary>
 /// Invokes an asynchronous action on each item in the collection in parallel
 /// </summary>
 /// <typeparam name="T">The type of an item</typeparam>
 /// <param name="enumerator">The collection of items to perform actions on</param>
 /// <param name="asyncItemAction">An asynchronous action to perform on the item</param>
 /// <param name="maxDegreeOfParallelism">Maximum items to schedule processing in parallel. The actual concurrency level depends on TPL settings. Set to 0 to choose a default value based on processor count.</param>
 /// <param name="breakLoopOnException">Set to True to stop processing items when first exception occurs. The result <see cref="AggregateException"/> might contain several exceptions though when faulty tasks finish at the same time.</param>
 /// <param name="gracefulBreak">If True (the default behavior), waits on completion for all started tasks when the loop breaks due to cancellation or an exception</param>
 /// <param name="cancellationToken">Cancellation token</param>
 /// <exception cref="ParallelForEachException">Wraps any exception(s) that occurred inside <paramref name="asyncItemAction"/></exception>
 /// <exception cref="OperationCanceledException">Thrown when the loop is canceled with <paramref name="cancellationToken"/></exception>
 public static Task ParallelForEachAsync <T>(
     this IAsyncEnumerator <T> enumerator,
     Func <T, Task> asyncItemAction,
     int maxDegreeOfParallelism,
     bool breakLoopOnException,
     bool gracefulBreak,
     CancellationToken cancellationToken = default)
 => enumerator.ParallelForEachAsync(
     (item, index) => asyncItemAction(item),
     maxDegreeOfParallelism,
     breakLoopOnException,
     gracefulBreak,
     cancellationToken);