using ConsoleApp;
#if false
class ThreadTest3
{
    // Member variablen werden automatisch initialisiert
    // lokale nicht
    // Csharp compiler gibt einen Error aus, wenn die Variable nicht initialisiert wird
    private bool done;
    static void Main()
    {
        ThreadTest3 tt = new ThreadTest3();
        new Thread(tt.Go).Start();
        tt.Go();
    }
    void Go()
    {
        if (!done)
        {
            // Thread.Sleep(10); ==> proviziert error
            done = true;
            Console.WriteLine("Done");
        }
    }
}
#endif

#if false
class ThreadTest7
{

    static void Main()
    {
        AdditionTask work1 = new AdditionTask("A", 100000000);
        AdditionTask work2 = new AdditionTask("B", 100000);
        AdditionTask work3 = new AdditionTask("C", 100);
        Thread t1 = new Thread(work1.Add);
        Thread t2 = new Thread(work2.Add);
        Thread t3 = new Thread(work3.Add);
        //t3.Priority = ThreadPriority.Lowest;
        t1.Start();
        t2.Start();
        t3.Start();
    }

}
#endif

#if false
class ThreadStop1
{
    static void Main()
    {
        try
        {
            Thread thread1 = new Thread(Go);
            thread1.Start();
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception!");
        }
    }

    private static void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
    {
        Console.WriteLine("Exception caught");
        throw new NotImplementedException();
    }

    static void Go()
    {
        throw null; // NullReferenceException wird ausgelöst
        Console.WriteLine("uups!");
    }

}

#endif

#if false
class ThreadStop2
{
    static void Main()
    {
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        new Thread(GoX).Start();
        new Thread(GoY).Start();
        Console.WriteLine("finished!");
    }

    private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Console.WriteLine("Unhandled exception " + e);
        throw new NotImplementedException();
    }

    static void GoX()
    {
        try
        {
            for (int i = 0; i < 10; i++)
            {
                Console.Write("X");
                if (i == 2)
                {
                    throw null; // NullReferenceException wird ausgelöst
                }
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception! " + ex.Message);
        }
    }

    static void GoY()
    {
        try
        {
            for (int i = 0; i < 10; i++)
            {
                Console.Write("Y");
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Exception! " + ex.Message);
        }
    }

}
#endif


#if false
class SimpleBlocking
{

    static void Main()
    {
        long sum = 0;
        bool fertig = false;
        Thread mainThread = Thread.CurrentThread;  // main thread

        Thread t = new Thread(delegate ()
        {
            for (int i = 0; i <= 1000; i++)
            {
                sum += i;
            }
            Console.WriteLine(mainThread.ThreadState);
            fertig = true;
        });

        t.Start();
        // Version 1  == zweitbeste Variante
        //while (!fertig) { Thread.Sleep(10) };

        // Version 2  == schlecht
        //Thread.Sleep(10);

        // Version 3  == beste Variante
        t.Join();  // warten bis dieser Thread t beendet wurde
        Console.WriteLine("Summe = " + sum);

    }

}

#endif

#if true

class LockingConstruct1 {
    private static object locker = new object();

    static void Main()
    {
        long sum = 0;

        Thread t1 = new Thread(delegate()
        {
            lock (locker)
            {
                for (int i = 0; i <= 1000; i++) {
                    sum += i;
                }
            }
        });

        Thread t2 = new Thread(delegate()
        {
            lock (locker)
            {
                Console.WriteLine("Summe = " + sum);
            }
        });

        t1.Start();
        t2.Start();
    }
}

#endif