English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

C# Multithreading

Thread defined as the execution path of a program. Each thread defines a unique control flow. If your application involves complex and time-consuming operations, it is often beneficial to set different execution paths for threads, with each thread performing specific tasks.

A thread isLightweight processA common example of using threads is the implementation of parallel programming in modern operating systems. Using threads saves CPU cycle waste and improves the efficiency of the application.

So far, the program we have written is a single-threaded process running as a single example of the application's operation. However, such an application can only execute one task at a time. To execute multiple tasks simultaneously, it can be divided into smaller threads.

Thread life cycle

The thread life cycle begins when an object of the System.Threading.Thread class is created, and ends when the thread is terminated or completed.

The following lists various states in the thread life cycle:

  • Unstarted state: The state when a thread instance is created but the Start method has not been called.

  • Ready state: The state when a thread is ready to run and waiting for CPU cycles.

  • Non-runnable state: The thread is not runnable in the following cases:

    • The Sleep method has been called

    • The Wait method has been called

    • Through I/O operation blocked

  • Dead state: The state when a thread has completed execution or has been aborted.

Main thread

In C#,System.Threading.Thread Class used for thread work. It allows creating and accessing a single thread in a multi-threaded application. The thread that is executed first in the process is calledMain thread.

When a C# program starts execution, the main thread is automatically created. Use Thread The thread created by the class is called by the child thread of the main thread. You can use the Thread class's CurrentThread Access properties of threads.

The following program demonstrates the execution of the main thread:

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class MainThreadProgram
    {
        static void Main(string[] args)
        {
            Thread th = Thread.CurrentThread;
            th.Name = "MainThread";
            Console.WriteLine("This is {0}", th.Name);
            Console.ReadKey();
        }
    }
}

When the above code is compiled and executed, it will produce the following results:

This is MainThread

Common properties and methods of the Thread class

The following table lists Thread Some commonly used methods of a class Properties:

PropertiesDescription
CurrentContextGet the current context in which the thread is executing.
CurrentCultureGet or set the current region of the current thread.
CurrentPrincipalGet or set the current owner of the thread (for role-based security).
CurrentThreadGet the current thread that is running.
CurrentUICultureGet or set the current region used by the resource manager to locate region-specific resources at runtime.
ExecutionContextObtain an ExecutionContext object that contains various context information about the current thread.
IsAliveGet a value that indicates the execution status of the current thread.
IsBackgroundGet or set a value that indicates whether a thread is a background thread.
IsThreadPoolThreadGet a value that indicates whether the thread belongs to the managed thread pool.
ManagedThreadIdGet the unique identifier of the current managed thread.
NameGet or set the name of the thread.
PriorityGet or set a value that indicates the scheduling priority of the thread.
ThreadStateGet a value that contains the current state of the thread.

The following table lists Thread Some commonly used methods of a class Method:

Serial numberMethod name & description
1public void Abort()
Throw a ThreadAbortException on the thread that calls this method to start the process of terminating this thread. Calling this method usually terminates the thread.
2public static LocalDataStoreSlot AllocateDataSlot()
Allocate unnamed data slots on all threads. For better performance, please use fields marked with the ThreadStaticAttribute attribute.
3public static LocalDataStoreSlot AllocateNamedDataSlot( string name)
Allocate named data slots on all threads. For better performance, please use fields marked with the ThreadStaticAttribute attribute.
4public static void BeginCriticalRegion()
Notify the host that the code is about to enter a region where the impact of thread termination or unhandled exceptions may harm other tasks in the application domain.
5public static void BeginThreadAffinity()
Notify the host that the managed code is about to execute instructions that depend on the identifier of the current physical operating system thread.
6public static void EndCriticalRegion()
Notify the host that the code is about to enter a region where thread termination or unhandled exceptions only affect the current task.
7public static void EndThreadAffinity()
Notify the host that the code has executed instructions that depend on the identifier of the current physical operating system thread.
8public static void FreeNamedDataSlot(string name)
Remove the association between name and slot for all threads in the process. For better performance, please use fields marked with the ThreadStaticAttribute attribute.
9public static Object GetData( LocalDataStoreSlot slot )
Retrieve the value from the specified slot on the current thread in the current domain of the current thread. For better performance, please use fields marked with the ThreadStaticAttribute attribute.
10public static AppDomain GetDomain()
Return the current domain in which the current thread is running.
11public static AppDomain GetDomainID()
Return a unique application domain identifier.
12public static LocalDataStoreSlot GetNamedDataSlot( string name )
Find the named data slot. For better performance, please use fields marked with the ThreadStaticAttribute attribute.
13public void Interrupt()
Interrupt the thread that is in the WaitSleepJoin thread state.
14public void Join()
Block the calling thread during the execution of standard COM and SendMessage message pump processing until a thread terminates. This method has different overloads.
15public static void MemoryBarrier()
Synchronize memory access as follows: When the processor of the current thread is performing instruction reordering, it cannot adopt the way of first executing memory access after the MemoryBarrier call and then executing memory access before the MemoryBarrier call.
16public static void ResetAbort()
Cancel the Abort requested for the current thread.
17public static void SetData( LocalDataStoreSlot slot, Object data )
Set data in the specified slot for the current domain of the thread that is currently running. For better performance, please use fields marked with the ThreadStaticAttribute attribute.
18public void Start()
Start a thread.
19public static void Sleep( int millisecondsTimeout )
Causes the thread to pause for a period of time.
20public static void SpinWait( int iterations )
Causes the thread to wait for the time defined by the iterations parameter.
21public static byte VolatileRead( ref byte address )
public static double VolatileRead( ref double address )
public static int VolatileRead( ref int address )
public static Object VolatileRead( ref Object address )

Read the field value. Regardless of the number of processors or the state of the processor cache, the value is written by any processor in the computer as the latest value. This method has different overloads. Here are some forms.
22public static void VolatileWrite( ref byte address, byte value )
public static void VolatileWrite( ref double address, double value )
public static void VolatileWrite( ref int address, int value )
public static void VolatileWrite( ref Object address, Object value )

Immediately writes a value to the field to make the value visible to all processors in the computer. This method has different overloads. Here are some forms.
23public static bool Yield()
Causes the calling thread to execute another thread that is ready to run on the current processor. The operating system selects the thread to be executed.

Thread creation

Threads are created by extending the Thread class. The extended Thread class calls Start() Methods to start the execution of a child thread.

The following program demonstrates this concept:

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

When the above code is compiled and executed, it will produce the following results:

In Main: Creating the Child thread
Child thread starts

Thread management

The Thread class provides various methods for thread management.

The following example demonstrates sleep() Method usage, used to pause a thread for a specific time.

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
            // Thread suspension 5000 milliseconds
            int sleepfor = 5000; 
            Console.WriteLine("Child Thread Paused for {0} seconds", 
                              sleepfor / 1000);
            Thread.Sleep(sleepfor);
            Console.WriteLine("Child thread resumes");
        }
        
        static void Main(string[] args)
        {
            ThreadStart childref = new ThreadStart(CallToChildThread);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            Console.ReadKey();
        }
    }
}

When the above code is compiled and executed, it will produce the following results:

In Main: Creating the Child thread
Child thread starts
Child Thread Paused for 5 seconds
Child thread resumes

Destroy thread

Abort() method is used to destroy threads.

by throwing threadabortexception Thread termination at runtime. This exception cannot be caught, if there is finally block, control will be sent to finally block.

The following program illustrates this:

using System;
using System.Threading;
namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            try
            {
                Console.WriteLine("Child thread starts");
                // Count up 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);
            Console.WriteLine("In Main: Creating the Child thread");
            Thread childThread = new Thread(childref);
            childThread.Start();
            // Stop the main thread for a while
            Thread.Sleep(2000);
            // Now aborting the child thread
            Console.WriteLine("In Main: Aborting the Child thread");
            childThread.Abort();
            Console.ReadKey();
        }
    }
}

When the above code is compiled and executed, it will produce the following results:

In Main: Creating the Child thread
Child thread starts
0
1
2
In Main: Aborting the Child thread
Thread Abort Exception
Couldn't catch the Thread Exception