Exemple #1
0
        public static Func <Task> ParallelForEach <T>(IQueueSource <T> source, ParallelWorker parallelWorker, Func <ForEachInfo <T>, Task> processAsync, Func <Task> onCloseAsync,
                                                      ExceptionCollector ec)
        {
            Func <Task> t = async delegate {
                IdleDetector idleDetector = new IdleDetector();
                try {
                    while (true)
                    {
                        var item = await source.Dequeue(ec.CancellationToken);

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

                        idleDetector.Enter();

                        await parallelWorker.StartWorkItem
                        (
                            async workerId => {
                            try {
                                await processAsync(new ForEachInfo <T>(itemValue, 0, workerId, ec.CancellationToken));
                            }
                            catch (Exception exc) {
                                ec.Add(exc);
                            }
                            finally {
                                idleDetector.Leave();
                            }
                        },
                            ec.CancellationToken
                        );
                    }
                }
                finally {
                    await idleDetector.WaitForIdle(CancellationToken.None);

                    if (onCloseAsync != null)
                    {
                        try {
                            await onCloseAsync();
                        }
                        catch (Exception exc) {
                            ec.Add(exc);
                        }
                    }
                }
            };

            return(t);
        }
        public static IQueueSource <T> ParallelWhere <T>(this IQueueSource <T> queue, ParallelWorker parallelWorker, Func <T, Task <bool> > predicate, int?capacity = null)
        {
            AsyncQueue <T> outQueue = new AsyncQueue <T>(capacity ?? 2);

            IdleDetector idleDetector = new IdleDetector();

            Func <Task> workPoster = async delegate {
                while (true)
                {
                    Option <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 {
                            if (await predicate(itemValue))
                            {
                                await outQueue.Enqueue(itemValue, CancellationToken.None);
                            }
                        }
                        finally {
                            idleDetector.Leave();
                        }
                    },
                        CancellationToken.None
                                     );
                }

                await idleDetector.WaitForIdle(CancellationToken.None);

                outQueue.WriteEof();
            };

            Task.Run(workPoster);

            return(outQueue);
        }