Dot Net For All

Multithreading in C# – Basics

Multithreading in C#

In this article I will discuss about the basics of multithreading in C#. First I will start with the threads in C#, what are they and why do they exist in .NET. After that I will discuss about having a multithreaded application in C# and Pros and cons or benefits and drawbacks of having a multithreading application in C# followed by canceling a thread and blocking mechanism using Join() method of a thread.

What is a Thread?

Each and every thread in windows is associated with a process.  A process is just a collection of resources that is used by a single instance of an application. Each process is given a virtual address space, ensuring that the code and data used by one process is not accessible to another process. That was about the process. Since a process is executed under the memory managed by the CPU what happens if the process is corrupted or it has hanged due to some long running data, the functioning of the CPU will be stuck.

To overcome this unresponsiveness of the CPU due to non-performing process was solved by introduction of threads in windows by Microsoft. A thread is a windows concept whose job is to virtualize the CPU. Windows give each process its own thread and if the application code enters an infinite loop, the process associated with that code freezes, but other process are not frozen.

As the thread are used to virtualize the CPU, it should be known that multiple threads can run at same time, but under the single CPU at one time only single thread is allowed to execute. This is achieved by context switching of the threads which is not obvious looking process

We can say following points about a thread in windows –

  1. Thread is used to execute code and it has access to all the data within the process.
  2. Each thread has its call stack.
  3. It is not possible to have a process operating without a thread. If the primary thread is terminated the process will also exit, if that is the only thread running in the application.

This was all about the basic of threads, multithreading in C# and process in windows applications.

In windows programming we can execute multiple threads in a single application or process. With the help of multiple threads we can achieve following results-

  1. For each and every UI application, there is a single thread, under the context of which the application runs. But if we are executing some long running task in that thread, there are chances that the UI of our application may be stuck for the time that task takes to complete. This can resolved by executing that long running task in other thread and hence maintaining the responsiveness of UI.
  2. There are two type of operation which are mainly performed by the any application. One is I/O bound and other is CPU bound. An I/O bound operation is the one in which the application waits for some outside operation to happen and then continue execution like downloading a webpage or calling console.Readline().With the help of multithreading we can perform CPU bound work while waiting for the I/O bound operations.

Drawbacks of multithreading in C#

  1. Slower executing – On a single core machine the task which is performed by single thread is performed much quicker than if the same task is performed by multiple threads due to context switching.
  2. Maintainability – It is difficult to maintain the code written performing tasks using multiple threads.
  3. Debug ability – Due to context switching it is very difficult to debug the code running with multiple threads.

Starting a thread in C# 

We can start a thread in C# by using the Thread class present under the System.Thread namespace in the following way.

 

        static void Main(string[] args)
        {
            Thread th = new Thread(SayHello);
            th.Name = "Hello";
            th.Priority = ThreadPriority.Normal;
            th.Start();
        }

        private static void SayHello()
        {
            Console.WriteLine("Hello world");
        }

Thread class constructor is overloaded to take two type of delegate methods i.e.

  1. ThreadStart – accepts method without any parameter
  2. ParameterizedThreadStart – accepts method with single parameter of object type.

In the above example I have created a thread instance using the ThreadStart delegate type parameter.

In the above code example you can see that I have assigned two properties for the thread class these are Name and Priority. Name property gives a name to the thread instance which can be helpful for debugging.

A thread’s Priority property determines how much execution time it gets relative to other active threads in operating system using the following values,

 

    public enum ThreadPriority
    {
        Lowest = 0,
        BelowNormal = 1,
        Normal = 2,
        AboveNormal = 3,
        Highest = 4
   }

The thread’s priority should be used with caution as elevating a thread’s priority can replenish other threads of the resources and it can keep them waiting for long time.

Please find below the example for the ParameetrizedThreadStart thread.

        static void Main(string[] args)
        {
            Thread th = new Thread(SayHello);
            th.Name = "Hello";
            th.Priority = ThreadPriority.Normal;
            th.Start("Vikram");
            Console.ReadLine();
        }

        private static void SayHello(object o)
        {
            Console.WriteLine("Hello " + (string)o);
        }

In the above example I am passing a string argument to SayHello method which accepts a parameter of type object. We need to take care of type casting this parameter while using it, otherwise it may result in exception.

Thread Lifetime

  1. In case of normal execution the threads stops execution as soon as it gets out of the referenced method. As in the case of the above code snippet the thread is stopped as soon as execution comes out of the method SayHello().
  2. In case of exception also the thread ends and the CLR does the cleanup.
  3. There is property IsAlive for a thread’s instance which can be used to determine if the thread is still operational or it is exited.

Shutting down A Thread

Till now II have discussed the ways to start  a thread and working with it. But suppose in case if you want to shut down the thread, how this can be achieved I will show you in this example along with the blocking mechanism which is used to wait for the executing thread.

There are definetly ways provided by the .NET framework like CancellationToken to stop a thread that I will discuss in my coming articles.

        static volatile bool cancelThread = false;

        static void Main(string[] args)
        {
            Thread th = new Thread(NewThreadExecution);
            th.Name = "Hello";
            th.Start();
            Console.WriteLine("Enter to cancel!!");
            Console.ReadLine();
            cancelThread = true;
            th.Join();
            Console.WriteLine("I am in main thread");
            Console.ReadLine();          
        }

        private static void NewThreadExecution()
        {
            while (!cancelThread)
            {
                Console.WriteLine("I am in seperate thread");
                Thread.Sleep(1000);
            }
        }

In the above code snippet I have created a thread and the thread continues to keep executing the NewThreadExecution() method as long as we don’t set the cancelThread variable to true which can be done by pressing enter.

I have used volatile keyword for cancelThread variable which you can read here.

But here we have to note one point is that that cancelling of the thread is not guaranteed as soon as we press the enter key, it just means that we have requested the thread to shutdown and we don’t know how long it is going to take for thread to check the condition due to Sleep or some long running task and check the request we have made.

In this example I have used Join() method, provided by the thread class. It is a blocking mechanism which is used to indicate the current thread(in our case the Main() methods thread) to wait until and unless the called thread(th in our case) is not done with its work and exited.
Join() method mainly checks the IsAlive property of the thread which we have discussed earlier.

Thread.Sleep() relinquishes the thread’s current time slice (which CPU has allocated while context switching) voluntarily handing over the CPU other threads. Thread.Yield() also does the same thing- except that it relinquished only to threads running on the same processor.

Ending the Article

In this article I have discussed about the basics of the threading including starting and stopping a thread, thread blocking , closing a thread and other important information. Though threading itself is a big topic, that is why I have planned multiple articles for that and this was one of them.

Going further you can read about thread pool here in my next article

 

 

Top career enhancing courses you can't miss

My Learning Resource

Excel your system design interview