public static List <ParallelAlgorithmPiece> CreatePieces(long priTotalElements, int priTotalParts)
        {
            // Always starts in element #0
            long liPieceSize;
            List <ParallelAlgorithmPiece> lloPieces;
            int  i;
            long liTotalCovered = 0;

            liPieceSize = (long)(priTotalElements / priTotalParts);

            lloPieces = new List <ParallelAlgorithmPiece>(priTotalParts);
            for (i = 0; i < priTotalParts; i++)
            {
                lloPieces[i]                 = new ParallelAlgorithmPiece();
                lloPieces[i].priBegin        = liTotalCovered;
                lloPieces[i].priEnd          = liTotalCovered + (liPieceSize - 1);
                lloPieces[i].priThreadNumber = i;
                if (lloPieces[i].priEnd > (priTotalElements - 1))
                {
                    lloPieces[i].priEnd = priTotalElements;
                }
                liTotalCovered += liPieceSize;
                if (liTotalCovered >= priTotalElements)
                {
                    break;
                }
            }

            return(lloPieces);
        }
        public void CreateThreads(long priTotalElements, int priTotalParts)
        {
            // priTotalParts should be Environment.ProcessorCount in most cases
            // Code added in the WaitHandle.WaitAll version
            // Create the AutoResetEvent array with the number of cores available
            praoAutoResetEventArray = new AutoResetEvent[priTotalParts];
            // End of the code added in the WaitHandle.WaitAll version

            prloPieces = ParallelAlgorithmPiece.CreatePieces(priTotalElements, priTotalParts);
            foreach (ParallelAlgorithmPiece loPiece in prloPieces)
            {
                // Create the new thread with parameters
                loPiece.poThread = new Thread(new ParameterizedThreadStart(loPiece.ThreadMethod));
                // Give the thread a name
                loPiece.poThread.Name = loPiece.piThreadNumber.ToString();

                // Code added in the WaitHandle.WaitAll version
                // Create a new AutoResetEvent instance for that thread with its initial state set to false
                loPiece.poAutoResetEvent = new AutoResetEvent(false);
                praoAutoResetEventArray[loPiece.piThreadNumber] = loPiece.poAutoResetEvent;
                // End of the code added in the WaitHandle.WaitAll version
            }
        }