Загрузка данных


using System.Diagnostics;

namespace ConsoleApp5
{
    internal class Program
    {
        static async Task Main(string[] args)
        {
            /*var thread = new Thread(() =>
            {
                Console.WriteLine("Thread started");
                Thread.Sleep(1000);
            })
            {
                IsBackground = true,
                Name = "Worker",
                Priority = ThreadPriority.BelowNormal,
            };
            thread.Start();
            thread.Join();*/

            /*int result = await Task.Run(()=>
            {
                return Enumerable.Range(1, 1_000_000).Sum(x => x % 7);
            });
            Console.WriteLine(result);*/

            const int limit = 5_000_000;
            Console.CursorVisible = false;
            Console.WriteLine("Counting prime numbers");
            Console.WriteLine("1 - in main thread");
            Console.WriteLine("2 - in Tast.Run()");

            var choice = Console.ReadKey(intercept: true).KeyChar;
            
            if(choice == '1')
            {
                
            }

            else if (choice == '2')
            {

            }
            Console.CursorVisible = true;

            static void RunBlocking(int limit)
            {
                Console.WriteLine("Counting...");
                var sw = Stopwatch.StartNew();
                int count = PrimeCounter.Count(limit,  progress: null, CancellationToken.None);
                Console.WriteLine($"Found {count} prime numbers in {sw.Elapsed.TotalSeconds} seconds");
            }
            static async Task RunWithTaskRun(int limit)
            {
                using var cts = new CancellationTokenSource();
                var progress = new ProgressState();
                var sw = Stopwatch.StartNew();

                Task<int> work = Task.Run(() => PrimeCounter.Count(limit, progress: null, CancellationToken.None));
                char[] spinner = ['|', '/', '-', '\\'];
                int frame = 0;

                while(!work.IsCompleted)
                {
                    if(Console.KeyAvailable&&Console.ReadKey(intercept: true).Key == ConsoleKey.Escape)
                    {
                        cts.Cancel();
                    }
                    Console.Write($"\r{spinner[frame++ % spinner.Length]}" +
                        $"{progress.Percent,3}% {sw.Elapsed:mm\\:ss\\.f} " +
                        $"(Esc - cancel)");
                    await Task.WhenAny(work, Task.Delay(100));
                }
                Console.WriteLine();

                try
                {
                    int count = await work;
                    Console.WriteLine($"{count} prinme numbers found");
                }
                catch (OperationCanceledException)
                {

                    Console.WriteLine($"Operation cancelled by user");
                }
            }
        }

        static class PrimeCounter
        {
            public static int Count(int limit, ProgressState? progress, CancellationToken token)
            {
                int count = 0;
                const int step = 50_000;
                for(int n = 2; n <= limit; n++)
                {
                    if(IsPrime(n))
                    {
                        count++;
                    }
                    if(n % step == 0)
                    {
                        token.ThrowIfCancellationRequested();
                        progress?.Report((int)100L * n/limit);
                    }
                }
                progress?.Report(100);
                return count;
            }
            private static bool IsPrime(int n)
            {
                if (n < 4) return n > 1;
                if (n % 2 == 0) return false;
                for (int d = 3; d * d <= n; d += 2)
                {
                    if (n % d == 0) return false;
                }
                return true;
            }

        }
        public sealed class ProgressState
        {
            private int _percent;
            public int Percent => Volatile.Read(ref _percent);
            public void Report(int value) => Volatile.Write(ref _percent, value);
        }
    }
}