Example #1
0
        public static IReadOnlyCollection <Exception> ForEach <T>(
            IEnumerable <T> items,
            Action <T> handleItem,
            DegreeOfParallelism?degreeOfParallelism = default,
            CancellationToken cancellationToken     = default)
        {
            var threadCount = (degreeOfParallelism ?? DegreeOfParallelism.Default).Value;
            var exceptions  = new ConcurrentBag <Exception>();

            using var blockingItems = new BlockingCollection <T>(new ConcurrentQueue <T>());

            var threads = Enumerable
                          .Range(0, threadCount)
                          .Select(index => new Thread(() =>
            {
                ForEachThreadLoop(
                    blockingItems,
                    handleItem,
                    exceptions,
                    cancellationToken);
            })
            {
                Name = $"{nameof(ParallelExecution)} [{index}]",
            })
                          .ToList();

            threads.ForEach(t => t.Start());

            blockingItems.AddRangeSafe(items, cancellationToken);
            blockingItems.CompleteAdding();

            threads.ForEach(t => t.Join());

            if (cancellationToken.IsCancellationRequested)
            {
                exceptions.Add(new OperationCanceledException(cancellationToken));
            }

            return(exceptions);
        }