Csharp 简明教程

C

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

A thread is defined as the execution path of a program. Each thread defines a unique flow of control. If your 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.

线程是 lightweight processes 。现代操作系统在实现并行编程时使用的线程是一个常见的示例。使用线程可以节省CPU周期的浪费并提高应用程序的效率。

Threads are lightweight processes. One common example of use of thread is implementation of concurrent programming by modern operating systems. Use of threads saves wastage of CPU cycle and increase efficiency of an application.

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

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

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

The life cycle of a thread starts when an object of the System.Threading.Thread class is created and ends when the thread is terminated or completes execution.

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

Following are the various states in the life cycle of a thread −

  1. The Unstarted State − It is the situation when the instance of the thread is created but the Start method is not called.

  2. The Ready State − It is the situation when the thread is ready to run and waiting CPU cycle.

  3. The Not Runnable State − A thread is not executable, when Sleep method has been calledWait method has been calledBlocked by I/O operations

  4. The Dead State − It is the situation when the thread completes execution or is aborted.

The Main Thread

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

In C#, the System.Threading.Thread class is used for working with threads. It allows creating and accessing individual threads in a multithreaded application. The first thread to be executed in a process is called the main thread.

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

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. You can access a thread using the CurrentThread property of the Thread class.

以下程序演示了主线程执行 −

The following program demonstrates main thread execution −

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 produces the following result −

This is MainThread

Properties and Methods of the Thread Class

下表显示了 Thread 类的部分常用 properties

The following table shows some most commonly used properties of the Thread class −

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 类中经常使用的一些 methods

The following table shows some of the most commonly used methods of the Thread class −

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.

Creating Threads

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

Threads are created by extending the Thread class. The extended Thread class then calls the Start() method to begin the child thread execution.

以下程序演示这个概念:

The following program demonstrates the 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 result −

In Main: Creating the Child thread
Child thread starts

Managing Threads

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

The Thread class provides various methods for managing threads.

以下示例演示如何使用 sleep() 方法使线程暂停一段时间。

The following example demonstrates the use of the sleep() method for making a thread pause for a specific period of time.

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

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

When the above code is compiled and executed, it produces the following result −

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

Destroying Threads

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

The Abort() method is used for destroying threads.

运行时将导致一个 ThreadAbortException 。此异常无法被捕获,控制权将(如果有的话)发送到 finally 块。

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 −

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

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

When the above code is compiled and executed, it produces the following result −

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