Ejemplo n.º 1
0
        /// <summary>
        /// Perform the specified async action on each element
        /// of the <see cref="List{T}"/> with the specified concurrency.
        /// </summary>
        public static Task ForEachAsync <T>(this IEnumerable <T> source, Func <T, Task> asyncAction, int concurrency,
                                            CancellationToken cancellationToken = default)
        {
            source.ThrowIfArgumentNull(nameof(source));
            asyncAction.ThrowIfArgumentNull(nameof(asyncAction));
            concurrency.ThrowIfArgumentOutOfRange(1, int.MaxValue, nameof(concurrency));

            async Task ForEachInner()
            {
                int throwedCount = 0;

                void OnFault(Exception e)
                {
                    Interlocked.Add(ref throwedCount, 1);
                    throw e;
                }

                using (var tasks = new TaskSet(concurrency, OnFault))
                {
                    foreach (var x in source)
                    {
                        if (throwedCount > 0)
                        {
                            break;
                        }
                        cancellationToken.ThrowIfCancellationRequested();

                        await tasks.AddAsync(x, asyncAction).ConfigureAwait(false);
                    }

                    await tasks.WhenAll().ConfigureAwait(false);
                }
            }

            return(ForEachInner());
        }