/// <summary>
        /// Read remarks.
        /// </summary>
        /// <typeparam name="TSource"></typeparam>
        /// <typeparam name="TResult"></typeparam>
        /// <typeparam name="TThrottle"></typeparam>
        /// <param name="enumerable"></param>
        /// <param name="selectKey"></param>
        /// <param name="initialBandwidth"></param>
        /// <param name="tag"></param>
        /// <returns></returns>
        /// <remarks>
        /// Throttling can only slow down iteration. Throttling cannot accelerate/force iteration. Therefore, unless the
        /// calling method requests the tasks in the returned enumeration faster than the tasks' Results are awaited,
        /// the iteration will be sequention and Throttle will have a negligable effect. More specifically,
        /// be sure to call a method such as Prespool, Batch, Array, etc before calling Await on the throttled IEnumerableAsync<Task<TResult>>.
        /// </remarks>
        public static IEnumerableAsync <Task <TResult> > Throttle <TSource, TResult, TThrottle>(this IEnumerableAsync <TSource> enumerable,
                                                                                                Func <TSource, IManagePerformance <TThrottle>, Task <TResult> > selectKey,
                                                                                                int desiredRunCount = 1,
                                                                                                ILogger log         = default(ILogger))
        {
            var logScope  = log.CreateScope($"Throttle[{Guid.NewGuid()}]");
            var throttler = new PerformanceManager <TThrottle>(desiredRunCount, logScope);

            return(enumerable
                   .Batch()
                   .SelectMany(
                       items =>
            {
                return items
                .Select(item => throttler.RunTask(() => selectKey(item, throttler)));
            }));
        }