Topic : Multi-threading Or Multi-Tasking in C# Programming Language:

What is Multi-threading?

Multi-threading or Multitasking is an art of handling different (More than one) task simultaneously at a given point of time. also called as Multi-processing:



Multi-threading : infobrother

It’s no secret that for many jobs multitasking is an essential requirement. A common example of multitasking at work is a representative juggling numerous tasks at once like talking on the telephone, taking notes and checking emails at the same time. we all have multitasking for each minute like we talk on the phone while driving, text while keeping conversation with friends, and constantly check emails while watching favorite shows etc.



Multi-Threading in C#:

A programmable approach to achieve multi-tasking in known as multi-threading. A multi threaded program contains two or more parts of the program that can run concurrently. Each part of such a program is called a thread , and each thread defines a separate path of execution.



What is Thread?

A thread is defined as the Execution path of a Program. Each thread defines a Unique flow of Control. if our Application involves complicated and time consuming operations, then it is often helpful to set different execution paths or threads, with each thread performing a particular job.

On the computer, a thread is a process moving through time. the Process performs sets of Sequential steps, each step executing a line of code. because the steps are Sequential, each step takes a given amount of time. The time it takes to complete a series of steps is the sum of the time it takes to perform each programming step.



What is Multi-threaded Application:

For a long time, most programming applications (except for embedded system programs) were single-threaded. That means there was only one thread in the entire application. We could never do computation "A" until completing computation "B". A program starts at step 1 and continues sequentially (step 2, step 3, step 4) until it hits the final step (call it step 10). A multi-threaded application allow us to run several threads, each thread running in its own process. So theoretically you can run step 1 in one thread and at the same time run step 2 in another thread. At the same time you could run step 3 in its own thread, and even step 4 in its own thread. Hence step 1, step 2, step 3, and step 4 would run concurrently. Theoretically, if all four steps took about the same time, you could finish your program in a quarter of the time it takes to run a single thread (assuming you had a 4 processor machine).



So far we wrote the programs where a single thread runs as a single process which is the running instance of the application. However, this way the application can perform one job at a time. To make it execute more than one task at a time, it could be divided into smaller threads.



Thread Life Cycle:

In C#, each thread has a life cycle. The life cycle of a thread is started when Object of System.Threading.Thread class is created. When the task execution of the thread is completed, its life cycle is ended.


  • Following are the various states in the life cycle of a thread:
    » Unstarted - It is the situation when the Object of the thread is created but the Start method is not called.

    » Runnable - It is the situation when the start() method is called and a thread is ready to run.

    » Running - Only one thread within a process can be executed at a time. At the time of execution, thread is in running state.

    » Not Runnable - The thread is in not runnable state, if sleep() or wait() method is called on the thread, or input/output operation is blocked.

    » Dead - After completing the task, thread enters into dead or terminated state.



Main Thread:

In C#, the System.Threading.Thread class is used for working with threads. It allows creating and accessing individual threads in a multi-threaded application. The first thread to be executed in a process is called the main thread. When a C# program starts execution, the main thread is automatically created. The threads created using the Thread class are called the child threads of the main thread. The following program demonstrates main thread execution:


/*Example - Multi-threading - InfoBrother*/

using System;
using System.Threading;

namespace Multi_Threading
{
    class Program
    {
        static void ThreadJob() 
        {
            for (int i = 0; i < 10; i++)
            {
                Console.WriteLine("Other thread: {0}", i);
                Thread.Sleep(500);
            }
        }

        static void Main(string[] args)
        {
            ThreadStart job = new ThreadStart(ThreadJob); //Unstarted State:
            Thread thread = new Thread(job); //thread is ready to run:
            thread.Start(); //Running:

            for (int i = 0; i < 5; i++)
            {
                Console.WriteLine("Main thread: {0}", i);
                Thread.Sleep(1000);  //sleep method is called: 
            }

            Console.ReadKey();

        }
    }
}


In Above Example, we create a new thread which runs the ThreadJob() Method, and start it. That thread counts from 0 to 9 fairly fast (about twice a second) while the main thread from 0 to 4 fairly slowly (about once a second). the way they count at different speeds is by each of them including a call to thread.sleep() which just makes the current thread sleep (do nothing) for the specified period of time. Between each count in the main thread we sleep for 1000ms. and between each count in the other thread we sleep for 500ms.



Properties of Thread Class:

C# Thread Class provides some properties to create and control threads. these properties are found in System.Threading Namespace.


PropertiesDescription
CurrentContextGets the current context in which the thread is executing.
CurrentCultureGets or sets the culture for the current thread.
CurrentPrincipleGets or sets the thread's current principal (for role-based security).
CurrentThreadGets the currently running thread.
CurrentUICultureGets or sets the current culture used by the Resource Manager to look up culture-specific resources at run-time.
ExecutionContextGets an ExecutionContext object that contains information about the various contexts of the current thread.
IsAliveGets a value indicating the execution status of the current thread.
IsBackgroundGets or sets a value indicating whether or not a thread is a background thread.
IsThreadPoolThreadGets a value indicating whether or not a thread belongs to the managed thread pool.
ManagedThreadIdGets a unique identifier for the current managed thread.
NameGets or sets the name of the thread.
PriorityGets or sets a value indicating the scheduling priority of a thread.
ThreadStateGets a value containing the states of the current thread.


Methods of Thread Class:

C# Thread Class provides some Methods to create and control threads. these Methods are found in System.Threading Namespace.


MethodsDescription
Abort()Raises a ThreadAbortException in the thread on which it is invoked, to begin the process of terminating the thread. Calling this method usually terminates the thread.
AllocateDataSlot()Allocates an unnamed data slot on all the threads. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
AllocateNamedDataSlot(string name)Allocates a named data slot on all threads. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
BeginCriticalRegion()Notifies a host that execution is about to enter a region of code in which the effects of a thread abort or unhandled exception might jeopardize other tasks in the application domain.
BeginThreadAffinity()Notifies a host that managed code is about to execute instructions that depend on the identity of the current physical operating system thread.
EndCriticalRegion()Notifies a host that execution is about to enter a region of code in which the effects of a thread abort or unhandled exception are limited to the current task.
EndThreadAffinity()Notifies a host that managed code has finished executing instructions that depend on the identity of the current physical operating system thread.
FreeNamedDataSlot(string name)Eliminates the association between a name and a slot, for all threads in the process. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
GetData(LocalDataStoreSlot slot)Retrieves the value from the specified slot on the current thread, within the current thread's current domain. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.
GetDomain()Returns the current domain in which the current thread is running.
GetDomainID()Returns a unique application domain identifier
Interrupt()Interrupts a thread that is in the WaitSleepJoin thread state.
Join()Blocks the calling thread until a thread terminates, while continuing to perform standard COM and SendMessage pumping. This method has different overloaded forms.
MemoryBarrier()Synchronizes memory access as follows: The processor executing the current thread cannot reorder instructions in such a way that memory accesses prior to the call to MemoryBarrier execute after memory accesses that follow the call to MemoryBarrier.
ResetAbort()Cancels an Abort requested for the current thread.
SetData(LocalDataStoreSlot slot, Object data)Sets the data in the specified slot on the currently running thread, for that thread's current domain. For better performance, use fields marked with the ThreadStaticAttribute attribute instead.
Start()Starts a thread.
Sleep(int millisecondsTimeout)Makes the thread pause for a period of time.
SpinWait(int iterations)Causes a thread to wait the number of times defined by the iterations parameter
VolatileRead(ref byte address)Reads the value of a field. The value is the latest written by any processor in a computer, regardless of the number of processors or the state of processor cache. This method has different overloaded forms.
VolatileWrite(ref byte address,byte value)Writes a value to a field immediately, so that the value is visible to all processors in the computer. This method has different overloaded forms.
Yield()Causes the calling thread to yield execution to another thread that is ready to run on the current processor. The operating system selects the thread to yield to.


Creating Threads:

We can create a Threads by Extending the Thread Class. Then the thread class will call start() method to begin the child thread Execution: Look at this example to know, how we can create an threads:


/*Example - Creating a Threads - InfoBrother*/

using System;
using System.Threading;

namespace Multi_Threading
{
    class Program
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
        }

        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread); //unstarted state: 
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);  //Runnable state:
            childThread.Start();  //Running state:

            Console.ReadKey();

        }
    }
}


Managing Threads:

The Thread class provides various methods for managing threads. The following example demonstrates the use of the sleep() method for making a thread pause for a specific period of time.


/*Example - Managing  a Threads - InfoBrother*/

using System;
using System.Threading;

namespace Multi_Threading
{
    class Program
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");

            // the thread is paused for 5000 milliseconds    
            Console.WriteLine("Child Thread Paused for {0} seconds", 5000 / 1000);
            Thread.Sleep(5000);  //sleep for 5 seconds:
            Console.WriteLine("Child thread resumes");
        }

        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread); //Unstarted State:
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref); //Runnable state:
            childThread.Start(); //Running state:

            Console.ReadKey();

        }
    }
}


Destroying Threads:

We can use Abort() method to destroy a threads: The runtime aborts the thread by throwing a ThreadAbortException. This exception cannot be caught, the control is sent to the finally block, if any. The following program illustrates this:


/*Example - Destroying  a Threads - InfoBrother*/

using System;
using System.Threading;

namespace Multi_Threading
{
    class Program
    {
        public static void CallToChildThread()
        {
            try  
            {
                Console.WriteLine("Child thread starts");

                // do some work, like counting to 10
                for (int counter = 0; counter <= 10; counter++)
                {
                    Thread.Sleep(500);
                    Console.WriteLine(counter);
                }

                Console.WriteLine("Child Thread Completed");
            }


            catch (ThreadAbortException e)
            {
                Console.WriteLine("Thread Abort Exception");
            }

            finally
            {
                Console.WriteLine("Couldn't catch the Thread Exception");
            }
        }

        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread); //Unstarted State:
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);  //Runable state:
            childThread.Start();  //Running:

            //stop the main thread for some time
            Thread.Sleep(2000);  //sleep for 2 second:

            //now abort the child
            Console.WriteLine("In Main: Aborting the Child thread");

            childThread.Abort();   //Abort the thread:

            Console.ReadKey();

        }
    }
}


  • Advantages of Multiple-Threads:

    Using more than one thread is one of the most powerful technique available in C# to increase responsiveness to the user and process the data necessary to get the job done at almost the same time. Our single Application could use multiple threads to accomplish the following tasks:

    » Communicate over a network, to a Web server, and to a database.
    » Perform operations that take a large amount of time
    » Distinguish tasks of varying priority.
    » Allow the user interface to remain responsive, while allocating time to background tasks.



  • Disadvantages of Multiple-Threads:

    It is Recommended to use a few threads as possible. thereby minimizing the use of Operation-system resources and Improving performance. Threading also has resource requirement and potential conflicts to be considered when designing our Application. The Resource requirement are as follows:

    » The system consumes memory for the context information required by processes.
    » Keeping track of a large number of threads consumes significant processor time.
    » Controlling code execution with many threads is complex, and can be a source of many bugs.
    » Destroying threads requires knowing what could happen and handling those issues.
    »

















I Tried my Best to Provide you complete Information regarding this topic in very easy and conceptual way. but still if you have any Problem to understand this topic, or do you have any Questions, Feel Free to Ask Question. i'll do my best to Provide you what you need.

Sardar Omar.
InfoBrother





WRITE FOR INFOBROTHER

Advertising






Advertisement