namespace AddisonWesley.Michaelis.EssentialCSharp.Chapter19.Listing19_09
{
    using System;
    using System.Diagnostics;
    using System.Threading;
    using System.Threading.Tasks;

    public class Program
    {
        public static Stopwatch clock = new Stopwatch();
        public static void Main()
        {
            ManualResetEventSlim resetEvent = new ManualResetEventSlim();
            try
            {
                clock.Start();

                // Rejestrowanie wywołania zwrotnego w celu otrzymywania powiadomień 
                // o nieobsłużonych wyjątkach.
#if NETCOREAPP1_1
                System.Threading.Tasks.TaskScheduler.UnobservedTaskException += (s, e) =>
                {
                    Message("Rozpoczynanie obsługi zdarzeń");
                    resetEvent.Set();
                };

                void Work()
                {
                    Task task = Task.Factory.StartNew(() =>
                    {
                        Message("Zgłaszanie wyjątku.");
                        throw new Exception();
                    });
                }
                Work();

                Task.Delay(5000);
                GC.Collect();
                GC.WaitForPendingFinalizers();
                GC.Collect();


#else
                Action<object, EventArgs> unhandledExcpetionHandler = (s, e) =>
                {
                    Message("Rozpoczynanie obsługi zdarzeń");
                    Delay(4000);
                };
                AppDomain.CurrentDomain.UnhandledException +=
                  (s, e) =>
                  {
                      Message("Rozpoczynanie obsługi zdarzeń");
                      Delay(4000);
                  };
                Thread thread = new Thread(() =>
                {
                    Message("Zgłaszanie wyjątku.");
                    throw new Exception();
                });
                thread.Start();

#endif
#if DEBUG1   
                resetEvent.Wait();
                {
#else
                if (!resetEvent.Wait(5000))
                {
                    throw new Exception("Przekroczono limit czasu w oczekiwaniu na obsługę wyjątku.");
#endif // DEBUG
                }
                //Delay(2000)
            }
            finally
            {
                Message("Wykonywanie bloku finally.");
            }
        }

        static void Delay(int i)
        {
            Message($"Usypianie na {i} ms");
            Thread.Sleep(i);
            Message("Wzbudzanie");
        }

        static void Message(string text)
        {
            Console.WriteLine(
                $"{Thread.CurrentThread.ManagedThreadId}:{text}");
        }
    }
}
