/// <summary>
        /// ParallelSelect
        /// </summary>
        /// <param name="queue"></param>
        /// <param name="parallelWorker"></param>
        /// <param name="func"></param>
        /// <param name="capacity"></param>
        /// <typeparam name="T"></typeparam>
        /// <typeparam name="U"></typeparam>
        /// <returns></returns>
        public static IQueueSource <U> ParallelSelect <T, U>(this IQueueSource <T> queue, ParallelWorker parallelWorker, Func <T, Task <U> > func, int?capacity = null)
        {
            AsyncQueue <U> outQueue = new AsyncQueue <U>(capacity ?? 2);

            IdleDetector idleDetector = new IdleDetector();

            Func <Task> workPoster = async delegate {
                while (true)
                {
                    Optional <T> item = await queue.Dequeue(CancellationToken.None);

                    if (!item.HasValue)
                    {
                        break;
                    }
                    T itemValue = item.Value;

                    idleDetector.Enter();

                    Task doingWork = await parallelWorker.StartWorkItem
                                     (
                        async (int workerId) => {
                        try {
                            U item2 = await func(itemValue);
                            await outQueue.Enqueue(item2, CancellationToken.None);
                        }
                        finally {
                            idleDetector.Leave();
                        }
                    },
                        CancellationToken.None
                                     );
                }

                await idleDetector.WaitForIdle(CancellationToken.None);

                outQueue.WriteEof();
            };

            Task.Run(workPoster);

            return(outQueue);
        }
Exemple #2
0
        public static Func <Task> ParallelForEach <T>(IQueueSource <T>[] sources, InputPriorities inputPriorities, ParallelWorker parallelWorker,
                                                      Func <ForEachInfo <T>, Task> processAsync, Func <Task> onCloseAsync, ExceptionCollector ec)
        {
            Func <Task> t = async delegate {
                IdleDetector idleDetector = new IdleDetector();
                try {
                    int    sourceCount           = sources.Length;
                    bool[] atEof                 = new bool[sourceCount];
                    RoundRobinLoopGenerator loop = new RoundRobinLoopGenerator(sourceCount, inputPriorities);
                    while (!(atEof.All(e => e)))
                    {
                        var ops = Utils.OperationStarters <int, Option <T> >();

                        loop.ForEach
                        (
                            j => { ops = ops.AddIf(!atEof[j], j, Utils.StartableGet <T, Option <T> >(sources[j], a => new Some <T>(a), new None <T>())); }
                        );

                        Tuple <int, Option <T> > result = await ops.CompleteAny(ec.CancellationToken);

                        if (result.Item2.HasValue)
                        {
                            int sourceIndex = result.Item1;
                            T   itemValue   = result.Item2.Value;

                            idleDetector.Enter();

                            await parallelWorker.StartWorkItem
                            (
                                async workerId => {
                                try {
                                    await processAsync(new ForEachInfo <T>(itemValue, sourceIndex, workerId, ec.CancellationToken));
                                }
                                catch (Exception exc) {
                                    ec.Add(exc);
                                }
                                finally {
                                    idleDetector.Leave();
                                }
                            },
                                ec.CancellationToken
                            );
                        }
                        else
                        {
                            atEof[result.Item1] = true;
                        }
                    }
                }
                finally {
                    if (onCloseAsync != null)
                    {
                        try {
                            await onCloseAsync();
                        }
                        catch (Exception exc) {
                            ec.Add(exc);
                        }
                    }
                }
            };

            return(t);
        }