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


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 = 2_000_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')
            {
                RunBlocking(limit);
            }

            else if (choice == '2')
            {
                await RunWithTaskRun(limit);
            }
            Console.CursorVisible = true;*/

            /*Task work = Task.Run(HardWork);
            while(!work.IsCompleted)
            {
                Console.WriteLine(".");
                Thread.Sleep(300);
            }*/

            /*using var cts = new CancellationTokenSource();
            cts.Cancel();
                
            Task<int> success = Task.Run(() => 42);
            Task<int> failure = Task.Run(() => int.Parse("abc"));
            Task<int> cancelled = Task.Run(() => 7, cts.Token);

            await Show("success", success);
            await Show("cancelled", cancelled);
            await Show("failure", failure);*/

            /*Console.WriteLine("Starting up...");
            Task<string> report = Task.Run(() => 
            {
                Thread.Sleep(10000);
                return $"Report ready...";
            });
            for (int i = 0; i <= 5; i++)
            {
                Console.WriteLine($"Main thread doing something {i}");
                Thread.Sleep(400);
            }
            Console.WriteLine("Done, waitong for the report...");
            string result = await report;
            Console.WriteLine(result);*/

            /*Task<int> a = Task.Run(() =>
            {
                Thread.Sleep(3000);
                Console.WriteLine("Task A done");
                return 1;
            });

            Task<int> b = Task.Run(() =>
            {
                Thread.Sleep(5000);
                Console.WriteLine("Task B done");
                return 2;
            });

            Task<int> c = Task.Run(() =>
            {
                Thread.Sleep(1000);
                Console.WriteLine("Task C done");
                return 3;
            });

            int[] results = await Task.WhenAll(a, b, c);
            Console.WriteLine("All task finished their job");*/

            /*Task<int> count = Task.Run(() => 42);
            Task<string> name = Task.Run(() => "Marcille");
            Task<bool> ok = Task.Run(() => true);

            await(Task.WhenAll(count, name, ok));

            int c = await count;
            string str = await name;
            bool o = await ok;

            Console.WriteLine($"{c}, {str}, {o}");*/

            /*Task<string> fast = Task.Run(() =>
            {
                Thread.Sleep(500);
                return $"Marcille";
            });

            Task<string> slow = Task.Run(() =>
            {
                Thread.Sleep(5000);
                return $"Ellicram";
            });

            var first = await Task.WhenAny(fast, slow);

            Console.WriteLine(await first);*/

            /*Task<int> work = Task.Run(() => { Thread.Sleep(5000); return 42; });

            Console.WriteLine(work.IsCompleted);
            Console.WriteLine(work.Status);

            int value = await work;
            Console.WriteLine(work.Status);
            Console.WriteLine(work.IsCompleted);
            Console.WriteLine(work.Status);*/

            /*Task<string> firstdish = Task.Run(() => Cook("Soup", 3000));
            Task<string> seconddish = Task.Run(() => Cook("Pasta", 5000));
            Task<string> thirddish = Task.Run(() => Cook("Happymeal", 1000));

            string[] dishes = await (Task.WhenAll(firstdish, seconddish, thirddish));

            foreach (var dish in dishes)
            {
                Console.WriteLine(dish);
            }*/

            Console.WriteLine("What is 7 * 8");

            Task<string> inputTask = Task.Run(() => Console.ReadLine());
            Task timer = Task.Delay(5000);

            Task first = await Task.WhenAny(inputTask, timer);

            if (first == inputTask)
            {
                string? answer = await inputTask;

                if (answer?.Trim() == "56")
                    Console.WriteLine("Correct");

                else
                    Console.WriteLine("Incorrect");
            }
            else
            {
                Console.WriteLine("Timeout");
            }
        }

        static string Cook(string dish, int seconds)
        {
            Console.WriteLine($"Dish: {dish} started cooking");
            Thread.Sleep( seconds );
            return $"Dish: {dish} started cooking, it was cooked for {seconds/1000} seconds";
        }
        static async Task Show(string name, Task<int> work)
        {
            try
            {
                int value = await work;
                Console.WriteLine($"{name}: value {value}");
            }
            catch (OperationCanceledException)
            {
                Console.WriteLine($"{name}: cancelled");
            }
            catch(Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine($"{name}: CRITICAL ERROR {ex.GetType().Name}");
            }
        }
        static async Task HardWork()
            {
                Thread.Sleep(15000);
            }
        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} prime numbers found");
                }
                catch (OperationCanceledException)
                {

                    Console.WriteLine($"Operation cancelled by user");
                }
                catch(Exception ex)
                {
                    Console.WriteLine(ex.Message);
                }
            }

        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);
        }
    }
}