C# Tutoriallogin
C# Tutorial
author:php.cn  update time:2022-04-11 14:06:23

C# multithreading



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

Threads are lightweight processes. A common example of the use of threads is the implementation of parallel programming in modern operating systems. Using threads saves wasted CPU cycles while increasing application efficiency.

The program we have written so far is a single thread running as a single process of the running instance of the application. However, this sub-application can only perform one task at a time. In order to perform 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 completes execution.

The following lists the various states in the thread life cycle:

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

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

  • Unrunnable state: The thread is not runnable in the following situations:


    • Sleep method has been called

    • Wait method has been called

    • Blocked by I/O operation

  • Death state: The situation when the thread has completed execution or has been terminated.

Main thread

In C#, the System.Threading.Thread class is used for the work of threads. It allows the creation and access of individual threads in multi-threaded applications. The first thread to be executed in the process is called main thread.

When the C# program starts executing, the main thread is automatically created. Threads created using the Thread class are called by child threads of the main thread. You can access threads using the CurrentThread property of the Thread class.

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

Thread class commonly used Properties and methods

The following table lists some commonly used properties of the Thread class:

PropertyDescription
CurrentContextGets the current context in which the thread is executing.
CurrentCultureGets or sets the culture of the current thread.
CurrentPrincipleGets or sets the current principal of the thread (for role-based security).
CurrentThreadGet the currently running thread.
CurrentUICultureGets or sets the current culture used by the resource manager to find culture-specific resources at runtime.
ExecutionContextGets an ExecutionContext object that contains information about various contexts for the current thread.
IsAliveGets a value that indicates the execution status of the current thread.
IsBackgroundGets or sets a value indicating whether a thread is a background thread.
IsThreadPoolThreadGets a value that indicates whether the thread belongs to a managed thread pool.
ManagedThreadIdGet the unique identifier of the current managed thread.
NameGets or sets the name of the thread.
PriorityGets or sets a value that indicates the thread's scheduling priority.
ThreadStateGets a value that contains the state of the current thread.

The following table lists some commonly used methods of the Thread class:

Serial numberMethod name & description
1public void Abort()
Throws a ThreadAbortException on the thread calling this method to begin 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, use fields marked with the ThreadStaticAttribute attribute instead.
3public static LocalDataStoreSlot AllocateNamedDataSlot( string name)
Allocate named data slots on all threads. For better performance, use fields marked with the ThreadStaticAttribute attribute instead.
4public static void BeginCriticalRegion()
Notifies the host that execution is about to enter a code area, and the thread is terminated in this code area Or the impact of an unhandled exception may harm other tasks in the application domain.
5public static void BeginThreadAffinity()
Notifies the host managed code that it is about to execute a thread that depends on the identity of the current physical operating system thread. instruction.
6public static void EndCriticalRegion()
Notify the host that execution is about to enter a code area, and the thread is terminated in this code area Or unhandled exceptions only affect the current task.
7public static void EndThreadAffinity()
Notifying the host that managed code has finished executing depends on the identity of the current physical operating system thread instructions.
8public static void FreeNamedDataSlot(string name)
Eliminate the association between the name and the slot for all threads in the process . For better performance, use fields marked with the ThreadStaticAttribute attribute instead.
9public static Object GetData( LocalDataStoreSlot slot )
Retrieves a value from the specified slot on the current thread in the current domain of the current thread. For better performance, use fields marked with the ThreadStaticAttribute attribute instead.
10public static AppDomain GetDomain()
Returns the current domain in which the current thread is running.
11public static AppDomain GetDomainID()
Returns a unique application domain identifier.
12public static LocalDataStoreSlot GetNamedDataSlot( string name )
Find a named data slot. For better performance, use fields marked with the ThreadStaticAttribute attribute instead.
13public void Interrupt()
Interrupt the thread in the WaitSleepJoin thread state.
14public void Join()
Blocks the calling thread until one of the threads terminates while standard COM and SendMessage message pump processing continues. There are different overloads of this method.
15public static void MemoryBarrier()
Synchronize memory access as follows: The processor executing the current thread When instructions are reordered, the memory access after the MemoryBarrier call cannot be performed first, and then the memory access before the MemoryBarrier call is performed.
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 this thread on the currently running thread. For better performance, use fields marked with the ThreadStaticAttribute attribute instead.
18public void Start()
Start a thread.
19public static void Sleep( int millisecondsTimeout )
Let the thread pause for a period of time.
20public static void SpinWait( int iterations )
Causes the thread to wait for the amount of 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( refObject address )

Read field value. This value is the most recent value written by any of the computer's processors, regardless of the number of processors or the state of the processor cache. There are different overloads of this method. Only some forms are given here.
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 write a value to the field so that the value is visible to all processors in the computer. There are different overloads of this method. Only some forms are given here.
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 which thread to execute.

Creating threads

Threads are created by extending the Thread class. The extended Thread class calls the Start() method to start the execution of the 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 produces the following results:

In Main: Creating the Child thread
Child thread starts

Managing threads

The Thread class provides various methods for managing threads.

The following example demonstrates the use of the sleep() method, which is used to pause the thread at a specific time.

using System;
using System.Threading;

namespace MultithreadingApplication
{
    class ThreadCreationProgram
    {
        public static void CallToChildThread()
        {
            Console.WriteLine("Child thread starts");
            // 线程暂停 5000 毫秒
            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 the thread

Abort() method is used Destroy the thread.

Abort a thread at runtime by throwing threadabortexception. This exception cannot be caught. If there is a finally block, control will be sent to the 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");
                // 计数到 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();
            // 停止主线程一段时间
            Thread.Sleep(2000);
            // 现在中止子线程
            Console.WriteLine("In Main: Aborting the Child thread");
            childThread.Abort();
            Console.ReadKey();
        }
    }
}

When the above code is compiled and executed, it produces 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

php.cn