📜  C#-多线程

📅  最后修改于: 2020-12-28 05:17:10             🧑  作者: Mango


线程被定义为程序的执行路径。每个线程定义唯一的控制流。如果您的应用程序涉及复杂且耗时的操作,那么设置不同的执行路径或线程(每个线程执行一个特定的工作)通常会很有帮助。

线程是轻量级进程。使用线程的一个常见示例是现代操作系统对并发编程的实现。使用线程可以节省CPU周期,并提高应用程序的效率。

到目前为止,我们已经编写了程序,其中单个线程作为单个进程运行,这是应用程序的运行实例。但是,通过这种方式,应用程序可以一次执行一项工作。为了使其一次执行多个任务,可以将其划分为较小的线程。

线程生命周期

线程的生命周期在创建System.Threading.Thread类的对象时开始,在线程终止或完成执行时结束。

以下是线程生命周期中的各种状态-

  • Unstarted状态-这是创建线程实例但未调用Start方法的情况。

  • 就绪状态-线程准备运行并等待CPU周期的情况。

  • 不可运行状态-线程不可执行

    • 睡眠方法已被调用
    • 等待方法已被调用
    • 被I / O操作阻塞
  • 死状态-线程完成执行或中止时的情况。

主线程

在C#中, System.Threading.Thread类用于处理线程。它允许在多线程应用程序中创建和访问各个线程。在进程中执行的第一个线程称为线程。

当C#程序开始执行时,将自动创建主线程。使用Thread类创建的线程称为主线程的子线程。您可以使用Thread类的CurrentThread属性访问线程。

以下程序演示了主线程的执行-

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();
      }
   }
}

编译并执行上述代码后,将产生以下结果-

This is MainThread

线程类的属性和方法

下表显示了Thread类的一些最常用的属性

Sr.No. Property & Description
1

CurrentContext

Gets the current context in which the thread is executing.

2

CurrentCulture

Gets or sets the culture for the current thread.

3

CurrentPrinciple

Gets or sets the thread’s current principal (for role-based security).

4

CurrentThread

Gets the currently running thread.

5

CurrentUICulture

Gets or sets the current culture used by the Resource Manager to look up culture-specific resources at run-time.

6

ExecutionContext

Gets an ExecutionContext object that contains information about the various contexts of the current thread.

7

IsAlive

Gets a value indicating the execution status of the current thread.

8

IsBackground

Gets or sets a value indicating whether or not a thread is a background thread.

9

IsThreadPoolThread

Gets a value indicating whether or not a thread belongs to the managed thread pool.

10

ManagedThreadId

Gets a unique identifier for the current managed thread.

11

Name

Gets or sets the name of the thread.

12

Priority

Gets or sets a value indicating the scheduling priority of a thread.

13

ThreadState

Gets a value containing the states of the current thread.

下表显示了Thread类最常用的一些方法

Sr.No. Method & Description
1

public void 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.

2

public static LocalDataStoreSlot AllocateDataSlot()

Allocates an unnamed data slot on all the threads. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.

3

public static LocalDataStoreSlot AllocateNamedDataSlot(string name)

Allocates a named data slot on all threads. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.

4

public static void 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.

5

public static void BeginThreadAffinity()

Notifies a host that managed code is about to execute instructions that depend on the identity of the current physical operating system thread.

6

public static void 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.

7

public static void EndThreadAffinity()

Notifies a host that managed code has finished executing instructions that depend on the identity of the current physical operating system thread.

8

public static void 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.

9

public static Object 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.

10

public static AppDomain GetDomain()

Returns the current domain in which the current thread is running.

11

public static AppDomain GetDomainID()

Returns a unique application domain identifier

12

public static LocalDataStoreSlot GetNamedDataSlot(string name)

Looks up a named data slot. For better performance, use fields that are marked with the ThreadStaticAttribute attribute instead.

13

public void Interrupt()

Interrupts a thread that is in the WaitSleepJoin thread state.

14

public void Join()

Blocks the calling thread until a thread terminates, while continuing to perform standard COM and SendMessage pumping. This method has different overloaded forms.

15

public static void 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.

16

public static void ResetAbort()

Cancels an Abort requested for the current thread.

17

public static void 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.

18

public void Start()

Starts a thread.

19

public static void Sleep(int millisecondsTimeout)

Makes the thread pause for a period of time.

20

public static void SpinWait(int iterations)

Causes a thread to wait the number of times defined by the iterations parameter

21

public 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)

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. Only some are given above.

22

public 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)

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. Only some are given above.

23

public static bool 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.

创建线程

通过扩展Thread类来创建线程。然后,扩展的Thread类将调用Start()方法以开始执行子线程。

以下程序演示了概念-

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();
      }
   }
}

编译并执行上述代码后,将产生以下结果-

In Main: Creating the Child thread
Child thread starts

管理线程

Thread类提供了各种管理线程的方法。

下面的示例演示了使用sleep()方法使线程在特定时间段内暂停。

using System;
using System.Threading;

namespace MultithreadingApplication {
   class ThreadCreationProgram {
      public static void CallToChildThread() {
         Console.WriteLine("Child thread starts");
         
         // the thread is paused for 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();
      }
   }
}

编译并执行上述代码后,将产生以下结果-

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

销毁线程

Abort()方法用于销毁线程。

运行时通过抛出ThreadAbortException中止线程。无法捕获此异常,控制将被发送到finally块(如果有)。

以下程序说明了这一点-

using System;
using System.Threading;

namespace MultithreadingApplication {
   class ThreadCreationProgram {
      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);
         Console.WriteLine("In Main: Creating the Child thread");
         
         Thread childThread = new Thread(childref);
         childThread.Start();
         
         //stop the main thread for some time
         Thread.Sleep(2000);
         
         //now abort the child
         Console.WriteLine("In Main: Aborting the Child thread");
         
         childThread.Abort();
         Console.ReadKey();
      }
   }
}

编译并执行上述代码后,将产生以下结果-

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