Thursday 16 March 2017

Threading 01 ThreadStart

Take a look at the Thread documentation 

Threading is the concept of doing two things at the same time or at least the appearance of it, for example we all remember applications that would freeze when long running tasks are required.

using System;
using System.Threading;

namespace pc.threadingExample
{
    class Program
    {
        static void LongRunningMethod()
        {
            Thread.Sleep(5000);
            Console.WriteLine("Hello");
        }
        static void Main(string[] args)
        {
            char inputChar;
            do
            {
                Console.WriteLine("1)say hi \n0)exit\n");
                inputChar = Console.ReadKey().KeyChar;
                if (inputChar == '1')
                    LongRunningMethod();
            } while (inputChar != '0');
        }
    }
}

if we take a look at the above program when we call our long running method we lose responsiveness for 5s; our app looks as if it's frozen which is a piss poor user experience, what we need to do is launch our long running method on a separate thread.

using System;
using System.Threading;

namespace pc.threadingExample
{
    class Program
    {
        static void LongRunningMethod()
        {
            Thread.Sleep(5000);
            Console.WriteLine("Hello");
        }
        static void Main(string[] args)
        {
            char inputChar;
            do
            {
                Console.WriteLine("1)say hi \n0)exit\n");
                inputChar = Console.ReadKey().KeyChar;
                if (inputChar == '1')
                    new Thread(LongRunningMethod).Start();
                   
            } while (inputChar != '0');
        }
    }

}

now by introducing threading we can now run our long running method parallel to our main thread not blocking it; one thing that you can notice is that if we hit 0 before our long running thread completes our app will wait for it to complete before terminating, this is because threads by default run in the foreground, which makes sense; if you had a thread running to save some data you probably would want that data to be saved before your application terminates.

however if you do want to ignore your threads you just have to set the IsBackground  property to true.

using System;
using System.Collections.Generic;
using System.Threading;

namespace pc.threadingExample
{
    class Program
    {
        static void LongRunningMethod()
        {
            Thread.Sleep(5000);
            Console.WriteLine("Hello");
        }
        static void Main(string[] args)
        {
            char inputChar;
            do
            {
                Console.WriteLine("1)say hi \n0)exit\n");
                inputChar = Console.ReadKey().KeyChar;
                if (inputChar == '1')
                {
                    var t = new Thread(LongRunningMethod);
                    t.IsBackground = true;
                    t.Start();
                }
                   
            } while (inputChar != '0');
        }
    }

}

and that's it, now our application will ignore any running threads a just shutdown when we want it to. however let's say that we want to join our long running threads back to our main, well all we'd have to do is store a reference to each thread and then just call it's join method

using System;
using System.Collections.Generic;
using System.Threading;

namespace pc.threadingExample
{
    class Program
    {
        static void LongRunningMethod()
        {
            Thread.Sleep(5000);
            Console.WriteLine("Hello");
        }
        static void Main(string[] args)
        {
            char inputChar;
            var threads = new List<Thread>();
            do
            {
                Console.WriteLine("1)say hi \n0)exit\n");
                inputChar = Console.ReadKey().KeyChar;
                if (inputChar == '1')
                {
                    var t = new Thread(LongRunningMethod);
                    t.IsBackground = true;
                    t.Start();
                    threads.Add(t);
                }
                   
            } while (inputChar != '0');

            foreach (var t in threads)
            {
                Console.WriteLine($"thread:{t.ManagedThreadId} joining");
                t.Join();
            }
        }
    }

}

our application will now pause and wait for the long running thread to complete and join back to the main