/// <summary>
        /// Constructs a new instance of ThreadedExecution class with the specified number of threads.
        /// </summary>
        /// <param name="input">array of input data packets</param>
        /// <param name="execBody">task execution method</param>
        /// <param name="threadCount">number of threads to run</param>
        /// <param name="parameters">global computation parameters</param>
        public ThreadedExecution(TInput[] input, ExecBody execBody, int threadCount, params object[] parameters)
        {
            if (threadCount < 0)
            {
                threadCount = Environment.ProcessorCount;
            }
            _in   = input;
            _out  = new TOutput[input.Length];
            _body = execBody;

            _params = parameters;

            _numDone     = 0;
            _numAssigned = 0;
            _aborted     = false;

            _threads = new Thread[threadCount];
            for (int i = 0; i < _threads.Length; i++)
            {
                _threads[i] = new Thread(ThreadBody);
            }
        }
 /// <summary>
 /// Constructs a new instance of ThreadedExecution class with the number of threads matching the number of available processors/cores.
 /// </summary>
 /// <param name="input">array of input data packets</param>
 /// <param name="execBody">task execution method</param>
 public ThreadedExecution(TInput[] input, ExecBody execBody)
     : this(input, execBody, Environment.ProcessorCount, null)
 {
 }
 /// <summary>
 /// Constructs a new instance of ThreadedExecution class with the specified number of threads.
 /// </summary>
 /// <param name="input">array of input data packets</param>
 /// <param name="execBody">task execution method</param>
 /// <param name="threadCount">number of threads to run</param>
 public ThreadedExecution(TInput[] input, ExecBody execBody, int threadCount)
     : this(input, execBody, threadCount, null)
 {
 }