예제 #1
0
        /// <summary>
        /// Invokes an action for each item of a sequence. Each thrown exception while invokation
        /// is collected and thrown or returned as an <see cref="AggregateException" />.
        /// </summary>
        /// <typeparam name="T">Type of the items of the sequence.</typeparam>
        /// <param name="items">The sequence.</param>
        /// <param name="action">The action to invoke for an item of <paramref name="items" />.</param>
        /// <param name="throwExceptions">Throw exception (<see langword="true" />) or return them (<see langword="false" />).</param>
        /// <returns>The list of thrown exception or <see langword="null" /> if no exception was thrown.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="items" /> and/or <paramref name="action" />
        /// are <see langword="null" />.
        /// </exception>
        /// <exception cref="AggregateException">
        /// At leat one exception was thrown. This only works if <paramref name="throwExceptions" />
        /// is <see langword="true" />.
        /// </exception>
        public static AggregateException ForAll <T>(IEnumerable <T> items,
                                                    Action <IForAllItemExecutionContext <T> > action,
                                                    bool throwExceptions)
        {
            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            return(ForAll <T, object>(items,
                                      delegate(IForAllItemExecutionContext <T, object> ctx)
            {
                SimpleForAllItemExecutionContext <T> ctxClone = new SimpleForAllItemExecutionContext <T>();
                ctxClone.Item = ctx.Item;

                action(ctxClone);
            },
                                      (object)null,
                                      throwExceptions));
        }
예제 #2
0
        /// <summary>
        /// Invokes an action for each item of a sequence. Each thrown exception while invokation
        /// is collected and thrown or returned as an <see cref="AggregateException" />.
        /// </summary>
        /// <typeparam name="T">Type of the items of the sequence.</typeparam>
        /// <typeparam name="S">Type of the second paramater of <paramref name="action" />.</typeparam>
        /// <param name="items">The sequence.</param>
        /// <param name="action">The action to invoke for an item of <paramref name="items" />.</param>
        /// <param name="actionStateFactory">
        /// The factory delegate that produces the value for the state argument of <paramref name="action" />.
        /// </param>
        /// <param name="throwExceptions">Throw exception (<see langword="true" />) or return them (<see langword="false" />).</param>
        /// <returns>The list of thrown exception or <see langword="null" /> if no exception was thrown.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="items" />, <paramref name="action" /> and/or <paramref name="actionStateFactory" />
        /// are <see langword="null" />.
        /// </exception>
        /// <exception cref="AggregateException">
        /// At leat one exception was thrown. This only works if <paramref name="throwExceptions" />
        /// is <see langword="true" />.
        /// </exception>
        public static AggregateException ForAll <T, S>(IEnumerable <T> items,
                                                       Action <IForAllItemExecutionContext <T, S> > action,
                                                       Func <T, long, S> actionStateFactory,
                                                       bool throwExceptions)
        {
            if (items == null)
            {
                throw new ArgumentNullException("items");
            }

            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            if (actionStateFactory == null)
            {
                throw new ArgumentNullException("actionStateFactory");
            }

            List <Exception> exceptions = new List <Exception>();

            try
            {
                using (IEnumerator <T> enumerator = items.GetEnumerator())
                {
                    long index = -1;

                    while (enumerator.MoveNext())
                    {
                        SimpleForAllItemExecutionContext <T, S> ctx = new SimpleForAllItemExecutionContext <T, S>();
                        try
                        {
                            ctx.Index = ++index;
                            ctx.Item  = enumerator.Current;
                            ctx.State = actionStateFactory(ctx.Item, ctx.Index);

                            action(ctx);
                        }
                        catch (Exception ex)
                        {
                            exceptions.Add(new ForAllItemExecutionException <T, S>(ctx, ex));
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                exceptions.Add(ex);
            }

            AggregateException result = null;

            if (exceptions.Count > 0)
            {
                result = new AggregateException(exceptions);
            }

            if (result != null &&
                throwExceptions)
            {
                throw result;
            }

            return(result);
        }
        // Public Methods (1) 

        /// <summary>
        /// Invokes an action for each item of a sequence. Each thrown exception while invokation
        /// is collected and thrown or returned as a single <see cref="AggregateException" />.
        /// The invokation of each action is done in an async thread, but it is wait until all actions were executed.
        /// </summary>
        /// <typeparam name="T">Type of the items of the sequence.</typeparam>
        /// <typeparam name="S">Type of the second paramater of <paramref name="action" />.</typeparam>
        /// <param name="items">The sequence.</param>
        /// <param name="action">The action to invoke for an item of <paramref name="items" />.</param>
        /// <param name="actionStateFactory">
        /// The factory delegate that produces the value for the state argument of <paramref name="action" />.
        /// </param>
        /// <param name="throwExceptions">Throw exception (<see langword="true" />) or return them (<see langword="false" />).</param>
        /// <returns>The list of thrown exception or <see langword="null" /> if no exception was thrown.</returns>
        /// <exception cref="ArgumentNullException">
        /// <paramref name="items" />, <paramref name="action" /> and/or <paramref name="actionStateFactory" />
        /// are <see langword="null" />.
        /// </exception>
        /// <exception cref="AggregateException">
        /// At leat one exception was thrown. This only works if <paramref name="throwExceptions" />
        /// is <see langword="true" />.
        /// </exception>
        public static AggregateException ForAllAsync <T, S>(IEnumerable <T> items,
                                                            Action <IForAllItemExecutionContext <T, S> > action,
                                                            Func <T, long, S> actionStateFactory,
                                                            bool throwExceptions)
        {
            if (items == null)
            {
                throw new ArgumentNullException("items");
            }

            if (action == null)
            {
                throw new ArgumentNullException("action");
            }

            if (actionStateFactory == null)
            {
                throw new ArgumentNullException("actionStateFactory");
            }

            var exceptions = new List <Exception>();
            var syncRoot   = new object();

            // create tuples from items
            long itemIndex = -1;
            var  tuples    = items.Select(i => new ForAllTuple <T, S>(
                                              action: action,
                                              actionStateFactory: actionStateFactory,
                                              exceptions: exceptions,
                                              index: ++itemIndex,
                                              item: i,
                                              syncRoot: syncRoot
                                              ));

            // create tasks from tuples
            var tasks = tuples.Select(t =>
            {
                return(new Task(action:
                                (state) =>
                {
                    var tuple = (ForAllTuple <T, S>)state;

                    var ctx = new SimpleForAllItemExecutionContext <T, S>();
                    try
                    {
                        ctx.Index = tuple.INDEX;
                        ctx.Item = tuple.ITEM;
                        ctx.State = tuple.ACTION_STATE_FACTORY(ctx.Item, ctx.Index);

                        tuple.ACTION(ctx);
                    }
                    catch (Exception ex)
                    {
                        lock (tuple.SYNC)
                        {
                            tuple.EXCEPTION_LIST
                            .Add(new ForAllItemExecutionException <T, S>(ctx, ex));
                        }
                    }
                }, state: t));
            });

            // start tasks and wait
            try
            {
                var runningTasks = new List <Task>();
                using (var enumerator = tasks.GetEnumerator())
                {
                    while (enumerator.MoveNext())
                    {
                        try
                        {
                            var t = enumerator.Current;

                            t.Start();
                            runningTasks.Add(t);
                        }
                        catch (Exception ex)
                        {
                            lock (syncRoot)
                            {
                                exceptions.Add(ex);
                            }
                        }
                    }
                }

                TaskHelper.WaitAll(runningTasks);
                runningTasks.Clear();
            }
            catch (Exception ex)
            {
                lock (syncRoot)
                {
                    exceptions.Add(ex);
                }
            }

            AggregateException result = null;

            lock (syncRoot)
            {
                if (exceptions.Count > 0)
                {
                    result = new AggregateException(exceptions);
                }
            }

            if (result != null &&
                throwExceptions)
            {
                throw result;
            }

            return(result);
        }