/// <summary>
        /// Add the specified <see cref="IFlowElement"/> array to the pipeline.
        /// These elements will all be started at the same time and executed
        /// in parallel using one thread for each element.
        /// </summary>
        /// <param name="elements">
        /// The <see cref="IFlowElement"/> array to add
        /// </param>
        /// <returns>
        /// This builder instance.
        /// </returns>
        /// <exception cref="ObjectDisposedException">
        /// Thrown if any of the elements have already been disposed.
        /// </exception>
        public T AddFlowElementsParallel(params IFlowElement[] elements)
        {
            // Check if any of the elements being added have already
            // been disposed
            var disposed = elements.FirstOrDefault(e => e.IsDisposed);

            if (disposed != null)
            {
                throw new ObjectDisposedException(nameof(disposed));
            }

            if (elements.Length == 1)
            {
                FlowElements.Add(elements[0]);
            }
            else if (elements.Length > 1)
            {
                var parallelElements = new ParallelElements(
                    LoggerFactory.CreateLogger <ParallelElements>(),
                    elements);
                FlowElements.Add(parallelElements);
            }

            return(this as T);
        }
        /// <summary>
        /// Create a <see cref="ParallelElements"/> from the specified
        /// configuration and add it to the _flowElements list.
        /// </summary>
        /// <param name="elements">
        /// The list to add the new <see cref="ParallelElements"/> to.
        /// </param>
        /// <param name="elementOptions">
        /// The <see cref="ElementOptions"/> instance to use when creating
        /// the <see cref="ParallelElements"/>.
        /// </param>
        /// <param name="elementIndex">
        /// The index of the element within the <see cref="PipelineOptions"/>.
        /// </param>
        private void AddParallelElementsToList(
            List <IFlowElement> elements,
            ElementOptions elementOptions,
            int elementIndex)
        {
            // Element contains further sub elements, this is not allowed.
            if (string.IsNullOrEmpty(elementOptions.BuilderName) == false ||
                (elementOptions.BuildParameters != null &&
                 elementOptions.BuildParameters.Count > 0))
            {
                throw new PipelineConfigurationException(
                          $"ElementOptions {elementIndex} contains both " +
                          $"SubElements and other settings values. " +
                          $"This is invalid");
            }
            List <IFlowElement> parallelElements = new List <IFlowElement>();

            // Iterate through the sub elements, creating them and
            // adding them to the list.
            int subCounter = 0;

            foreach (var subElement in elementOptions.SubElements)
            {
                if (subElement.SubElements != null &&
                    subElement.SubElements.Count > 0)
                {
                    throw new PipelineConfigurationException(
                              $"ElementOptions {elementIndex} contains nested " +
                              $"sub elements. This is not supported.");
                }
                else
                {
                    AddElementToList(parallelElements, subElement,
                                     $"element {subCounter} in element {elementIndex}");
                }
                subCounter++;
            }
            // Now we've created all the elements, create the
            // ParallelElements instance and add it to the pipeline's
            // elements.
            var parallelInstance = new ParallelElements(
                LoggerFactory.CreateLogger <ParallelElements>(),
                parallelElements.ToArray());

            elements.Add(parallelInstance);
        }