public static void Main(String[] args)
        {
            const Int32 maxBound = 10000000;

            // Кількість ядер на даному ПК
            Int32 coresNumber = Environment.ProcessorCount;

            Thread[]   threads   = new Thread[coresNumber - 1];
            FuncInfo[] funcInfos = new FuncInfo[coresNumber];

            Int32 iterationsPerThread = maxBound / coresNumber;
            Int32 i, currentStartNumber;

            for (i = 0, currentStartNumber = 0; i < coresNumber - 1; i++, currentStartNumber += iterationsPerThread)
            {
                funcInfos[i] = new FuncInfo(currentStartNumber + 1, currentStartNumber + iterationsPerThread);

                threads[i] = new Thread(PrintPrimeCount);
                threads[i].Start(funcInfos[i]);
            }

            funcInfos[i] = new FuncInfo(currentStartNumber + 1, currentStartNumber + iterationsPerThread);

            PrintPrimeCount(funcInfos[i]);

            for (Int32 j = 0; j < threads.Length; j++)
            {
                threads[j].Join();
            }

            Int32 result = funcInfos.Select(fi => fi.Result).Sum();

            Console.WriteLine($"There are {result} prime numbers between 0..10 000 000");
            Console.WriteLine("Program has finished!!!");
        }
        public static void PrintPrimeCount(Object obj)
        {
            // Кількість простих чисел на даному відрізку
            Int32    count    = 0;
            FuncInfo funcInfo = (FuncInfo)obj;

            for (Int32 currentNumber = funcInfo.StartNumber; currentNumber <= funcInfo.EndNumber; currentNumber++)
            {
                if (IsPrime(currentNumber))
                {
                    count++;
                }
            }

            Console.WriteLine(
                $"There are {count} prime numbers between {funcInfo.StartNumber}..{ funcInfo.EndNumber}");

            // Записуємо результат роботи потоку
            funcInfo.Result = count;
        }