private List <R> ParallelExecute <T, R>(ICollection <InputGroup <T> > inputGroups,
                                                IGroupedCallback <T, R> firstCallback, IGroupedCallback <T, R> callback)
        {
            var restResultFutures = AsyncExecute(inputGroups.Skip(1).ToList(), callback);

            return(GetGroupResults(SyncExecute(inputGroups.First(), null == firstCallback ? callback : firstCallback),
                                   restResultFutures));
        }
        /**
         * Execute.
         *
         * @param inputGroups input groups
         * @param firstCallback first grouped callback
         * @param callback other grouped callback
         * @param serial whether using multi thread execute or not
         * @param <I> type of input value
         * @param <O> type of return value
         * @return execute result
         * @throws SQLException throw if execute failure
         */
        public List <R> Execute <T, R>(ICollection <InputGroup <T> > inputGroups, IGroupedCallback <T, R> firstCallback,
                                       IGroupedCallback <T, R> callback, bool serial)
        {
            if (inputGroups.IsEmpty())
            {
                return(new List <R>(0));
            }

            return(serial
                ? SerialExecute(inputGroups, firstCallback, callback)
                : ParallelExecute(inputGroups, firstCallback, callback));
        }
        private ICollection <Task <ICollection <R> > > AsyncExecute <T, R>(List <InputGroup <T> > inputGroups,
                                                                           IGroupedCallback <T, R> callback)
        {
            ICollection <Task <ICollection <R> > > result = new LinkedList <Task <ICollection <R> > >();

            foreach (var inputGroup in inputGroups)
            {
                result.Add(AsyncExecute(inputGroup, callback));
            }

            return(result);
        }
        private List <R> SerialExecute <T, R>(ICollection <InputGroup <T> > inputGroups,
                                              IGroupedCallback <T, R> firstCallback, IGroupedCallback <T, R> callback)
        {
            ICollection <R> result =
                new LinkedList <R>(SyncExecute(inputGroups.First(), null == firstCallback ? callback : firstCallback));
            var loopInputGroups = inputGroups.Skip(1);

            foreach (var inputGroup in loopInputGroups)
            {
                result.AddAll(SyncExecute(inputGroup, callback));
            }

            return(result.ToList());
        }
 private ICollection <R> SyncExecute <T, R>(InputGroup <T> inputGroup, IGroupedCallback <T, R> callback)
 {
     return(callback.Execute(inputGroup.Inputs, true, new Dictionary <string, object>()));
 }
 /**
  * Execute.
  *
  * @param inputGroups input groups
  * @param callback grouped callback
  * @param <I> type of input value
  * @param <O> type of return value
  * @return execute result
  * @throws SQLException throw if execute failure
  */
 public List <R> Execute <T, R>(ICollection <InputGroup <T> > inputGroups, IGroupedCallback <T, R> callback)
 {
     return(Execute(inputGroups, null, callback, false));
 }
        private Task <ICollection <R> > AsyncExecute <T, R>(InputGroup <T> inputGroup, IGroupedCallback <T, R> callback)
        {
            IDictionary <string, object> dataMap = new Dictionary <string, object>();

            return(Task.Run(() => callback.Execute(inputGroup.Inputs, false, dataMap)));
        }