/// <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)); }
/// <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); }