9/12/2013

Switching between two threads in console application

I will present a very simple idea of switching between two threads. The switch can be done by user pressing the enter key or by timer.

This is an idea which I am going to use to switch between main and backup service.
In my case I am getting the data from TCP stream. It is AIS data, and if one of the streams do not receive data, should be able to switch to backup stream.

This is the example which used the user key pressing:

using System;
using System.Threading;

class Demo1
{
    /*
     * Switch between two threads. When the user presses enter key, he wakes up one of the two threads dependig on counter.
     * When the counter reaches 10, then a variable inside the threads is set to true - which indicates that the thread will finish.
     * The body of the thread is executed one more time.
     *
     *
     *
     */

    static readonly object _locker1 = new object();
    static readonly object _locker2 = new object();

    //private static EventWaitHandle _mainWait = new AutoResetEvent(false);

    static bool exit_1 = false;
    static bool exit_2 = false;

    static void Main()
    {
        new Thread(Work1).Start();
        new Thread(Work2).Start();

        int x2 = 0;

        while (true)
        {

            Console.ReadLine(); // Wait for user to hit Enter
            x2 += 1;

            Console.WriteLine(x2);

            if (x2 % 10 == 0)
            {
                //_mainWait.Set();
                lock (_locker1)
                {
                    exit_1 = true;
                    Monitor.Pulse(_locker1);
                }
                lock (_locker2)
                {
                    exit_2 = true;
                    Monitor.Pulse(_locker2);
                }

                break;
            }

            if (x2 % 2 == 0)
            {
                lock (_locker1) // Let's now wake up the thread by
                {
                    // setting _go=true and pulsing.
                    Monitor.Pulse(_locker1);
                }
            }
            else
            {
                lock (_locker2) // Let's now wake up the thread by
                {
                    // setting _go=true and pulsing.
                    Monitor.Pulse(_locker2);
                }
            }
        }

        //_mainWait.WaitOne();
    }

    static void Work1()
    {
        lock (_locker1)
        {
            while (true)
            {
                Monitor.Wait(_locker1); // Lock is released while we’re waiting
                if (!exit_1)
                    Console.WriteLine("Worker1 - Woken!!!");
                else
                    Console.WriteLine("lastly called worker1");
                //Monitor.Wait(_locker1);
                if (exit_1)
                    break;
            }
        }
    }

    static void Work2()
    {
        lock (_locker2)
        {
            while (true)
            {
                Monitor.Wait(_locker2); // Lock is released while we’re waiting
                if (!exit_2)
                    Console.WriteLine("Worker2 - Woken!!!");
                else
                    Console.WriteLine("lastly called worker2");
                //Monitor.Wait(_locker2);
                if (exit_2)
                    break;

            }
        }
    }
}

Example with automatic switch done by timer:
using System;
using System.Threading;
using System.Timers;

class Demo1
{
    /*
     * Switch between two threads. When the user presses enter key, he wakes up one of the two threads dependig on counter.
     * When the counter reaches 10, then a variable inside the threads is set to true - which indicates that the thread will finish.
     * The body of the thread is executed one more time.
     *
     *
     *
     */

    static readonly object _locker1 = new object();
    static readonly object _locker2 = new object();

    static readonly object _locker3 = new object();

    public static System.Timers.Timer HealthCheckTimer = new System.Timers.Timer();
    public static System.Timers.Timer HealthCheckTimerBackup = new System.Timers.Timer();
   
    //private static EventWaitHandle _mainWait = new AutoResetEvent(false);
   
    static bool exit_1 = false;
    static bool exit_2 = false;

    static void Main()
    {                                
        new Thread(Work1).Start();  
        new Thread(Work2).Start();
       
        int x2 = 0;
        HealthCheckTimer.Elapsed += new ElapsedEventHandler(OnElapsedTime);
        HealthCheckTimer.Interval = 100;
        HealthCheckTimer.Enabled = true;

        while (true)
        {
            lock (_locker3)
            {
                Monitor.Wait(_locker3);
            }

            x2 += 1;
           
            Console.WriteLine(x2);

            if (x2 % 10 == 0)
            {
                lock (_locker1)
                {
                    exit_1 = true;
                    Monitor.Pulse(_locker1);
                }
                lock (_locker2)
                {
                    exit_2 = true;
                    Monitor.Pulse(_locker2);  
                }

                break;
            }

            if (x2 % 2 == 0)
            {
                lock (_locker1)
                {
                    Monitor.Pulse(_locker1);
                }
            }
            else
            {
                lock (_locker2)
                {
                    Monitor.Pulse(_locker2);
                }
            }
        }
       
        //_mainWait.WaitOne();
    }

    private static void OnElapsedTime(object sender, ElapsedEventArgs e)
    {
        lock (_locker3)
        {
            Monitor.Pulse(_locker3);
        }
    }

    static void Work1()
    {
        lock (_locker1)
        {
            while (true)
            {
                Monitor.Wait(_locker1); // Lock is released while we’re waiting
                if(!exit_1)
                    Console.WriteLine("Worker1 - Woken!!!");
                else
                    Console.WriteLine("lastly called worker1");
                //Monitor.Wait(_locker1);
                if(exit_1)
                    break;
            }
        }
    }

    static void Work2()
    {
        lock (_locker2)
        {
            while (true)
            {
                Monitor.Wait(_locker2); // Lock is released while we’re waiting
                if(!exit_2)
                    Console.WriteLine("Worker2 - Woken!!!");
                else
                    Console.WriteLine("lastly called worker2");
                //Monitor.Wait(_locker2);
                if(exit_2)
                    break;
               
            }
        }
    }
}