using System;
using System.Threading;

namespace ex_050_003_Variables_locales_et_partagées_entre_threads
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("TEST 1 : utilisation d'une variable locale");
            Console.WriteLine("2 threads lancent une même méthode, initialisant une variable locale à la méthode à false");
            Console.WriteLine("affichant sa valeur, puis la passant à true.");
            Console.WriteLine("On lance le premier thread 1 seconde avant le 2ème.");
            Console.WriteLine("On peut voir ci-dessous que les variables locales ne sont pas partagées");

            Thread thread1 = new Thread(Test.MéthodeAvecVariableLocale) { Name = "thread1" };
            thread1.Start();
            Thread.Sleep(1000);

            Thread thread2 = new Thread(Test.MéthodeAvecVariableLocale) { Name = "thread2" };
            thread2.Start();

            thread1.Join();
            thread2.Join();

            Console.WriteLine("Appuyez sur une touche pour continuer");
            Console.ReadLine();

            Console.Clear();
            Console.WriteLine("TEST 2 : utilisation d'une seule variable statique");
            Console.WriteLine("2 threads lancent une même méthode statique,");
            Console.WriteLine("affichant la valeur d'un membre statique, puis le passant à true s'il vaut false.");
            Console.WriteLine("On lance le premier thread 1 seconde avant le 2ème.");
            Console.WriteLine("On peut voir ci-dessous que les variables statiques sont partagées entre les threads.");

            thread1 = new Thread(Test.MéthodeAvecVariablePartagée) { Name = "thread1" };
            thread1.Start();
            Thread.Sleep(1000);

            thread2 = new Thread(Test.MéthodeAvecVariablePartagée) { Name = "thread2" };
            thread2.Start();

            thread1.Join();
            thread2.Join();

            Console.WriteLine("Appuyez sur une touche pour continuer");
            Console.ReadLine();

            Console.Clear();
            Console.WriteLine("TEST 3 : utilisation de deux instances d'une classe utilisant un membre d'instance");
            Console.WriteLine("2 threads lancent une même méthode d'instance, mais à partir de deux instances différentes.");
            Console.WriteLine("Cette méthode affiche la valeur d'un membre d'instance, puis le passe à true s'il vaut false.");
            Console.WriteLine("On lance le premier thread 1 seconde avant le 2ème.");
            Console.WriteLine("On peut voir ci-dessous que les variables d'instance ne sont pas partagées entre les threads, si les instances sont différentes.");

            Test test = new Test();
            thread1 = new Thread(test.MéthodeAvecMembreDInstance) { Name = "thread1" };
            thread1.Start();
            Thread.Sleep(1000);

            Test test2 = new Test();
            thread2 = new Thread(test2.MéthodeAvecMembreDInstance) { Name = "thread2" };
            thread2.Start();

            thread1.Join();
            thread2.Join();

            Console.WriteLine("Appuyez sur une touche pour continuer");
            Console.ReadLine();

            Console.Clear();
            Console.WriteLine("TEST 4 : utilisation d'une seule instance d'une classe utilisant un membre d'instance");
            Console.WriteLine("2 threads lancent une même méthode d'instance, mais à partir d'une seule instance.");
            Console.WriteLine("Cette méthode affiche la valeur d'un membre d'instance, puis le passe à true s'il vaut false.");
            Console.WriteLine("On lance le premier thread 1 seconde avant le 2ème.");
            Console.WriteLine("On peut voir ci-dessous que les variables d'instance sont partagées entre les threads, si l'instance est partagée.");

            Test test3 = new Test();
            thread1 = new Thread(test3.MéthodeAvecMembreDInstance) { Name = "thread1" };
            thread1.Start();
            Thread.Sleep(1000);

            thread2 = new Thread(test3.MéthodeAvecMembreDInstance) { Name = "thread2" };
            thread2.Start();

            thread1.Join();
            thread2.Join();
        }
    }

    class Test
    {
        //méthode utilisée pour le TEST 1
        public static void MéthodeAvecVariableLocale()
        {
            bool localTest = false;
            Console.WriteLine("test ({0}) = {1}", Thread.CurrentThread.Name, localTest);
            if (!localTest)
            {
                localTest = true;
            }
            Thread.Sleep(1200);
        }
        
        //membre statique utilisé pour le TEST 2
        static bool staticTest = false;

        //méthode utilisée pour le TEST 2
        public static void MéthodeAvecVariablePartagée()
        {
            Console.WriteLine("staticTest ({0}) = {1}", Thread.CurrentThread.Name, staticTest);
            if (!staticTest)
            {
                staticTest = true;
            }
            Thread.Sleep(1200);
        }

        //membre d'instance utilisé pour les tests TEST 3 et TEST 4
        bool instanceTest = false;

        //méthode utilisée pour les tests TEST 3 et TEST 4
        public void MéthodeAvecMembreDInstance()
        {
            Console.WriteLine("instanceTest ({0}) = {1}", Thread.CurrentThread.Name, instanceTest);
            if (!instanceTest)
            {
                instanceTest = true;
            }
            Thread.Sleep(1200);
        }
    }
}
