线程是轻量级进程。一个使用线程的常见实例是现代操作系统中并行编程的实现。使用线程节省了 CPU 周期的浪费,同时提高了应用程序的效率。每个线程都定义了一个独特的控制流。如果应用程序涉及到复杂的和耗时的操作,那么设置不同的线程执行路径往往是有益的,每个线程执行特定的工作。
线程生命周期
线程生命周期开始于 System.Threading.Thread 类的对象被创建时,结束于线程被终止或完成执行时。
线程生命周期中的各种状态:
- 未启动状态:当线程实例被创建但 Start 方法未被调用时的状况。
- 就绪状态:当线程准备好运行并等待 CPU 周期时的状况。
- 不可运行状态:下面的几种情况下线程是不可运行的:
已经调用 Sleep 方法
已经调用 Wait 方法
通过 I/O 操作阻塞 - 死亡状态:当线程已完成执行或已中止时的状况。
Thread 类常用的属性和方法
1、属性
属性 | 描述 |
---|---|
CurrentContext | 获取线程正在其中执行的当前上下文。 |
CurrentThread | 获取当前正在运行的线程。 |
ExecutionContext | 获取一个 ExecutionContext 对象,该对象包含有关当前线程的各种上下文的信息。 |
IsAlive | 获取一个值,该值指示当前线程的执行状态。 |
IsBackground | 获取或设置一个值,该值指示某个线程是否为后台线程。 |
IsThreadPoolThread | 获取一个值,该值指示线程是否属于托管线程池。 |
ManagedThreadId | 获取当前托管线程的唯一标识符。 |
Name | 获取或设置线程的名称。 |
Priority | 获取或设置一个值,该值指示线程的调度优先级。 |
ThreadState | 获取一个值,该值包含当前线程的状态。 |
2、方法
方法 | 描述 |
---|---|
public void Abort() | 在调用此方法的线程上引发 ThreadAbortException,以开始终止此线程的过程。调用此方法通常会终止线程。 |
public static void ResetAbort() | 取消为当前线程请求的 Abort。 |
public void Interrupt() | 中断处于 WaitSleepJoin 线程状态的线程。 |
public void Join() | 在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止为止。 |
public static Object GetData( LocalDataStoreSlot slot ) | 在当前线程的当前域中从当前线程上指定的槽中检索值。 |
public static void SetData( LocalDataStoreSlot slot, Object data ) | 在当前正在运行的线程上为此线程的当前域在指定槽中设置数据。 |
public void Start() | 开始一个线程。 |
public static void Sleep( int millisecondsTimeout ) | 让线程暂停一段时间。 |
public static void SpinWait( int iterations ) | 使线程等待由 iterations 参数定义的时间量。 |
public static bool Yield() | 调用线程执行准备好在当前处理器上运行的另一个线程。由操作系统选择要执行的线程。 |
实例:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
namespace ThreadTestConsoleApp
{
class Program
{
static void Main(string[] args)
{
Thread[] newThreads = new Thread[4];
for (int i = 0; i < newThreads.Length; i++)
{
newThreads[i] =
new Thread(Slot.SlotTest);
newThreads[i].Start();
}
Console.ReadKey();
}
}
class Slot
{
static Random randomGenerator = new Random();
public static void SlotTest()
{
Thread.SetData(
Thread.GetNamedDataSlot("Random"),
randomGenerator.Next(1, 200));
Thread.Sleep(1000);
Other o = new Other();
o.ShowSlotData();
}
}
public class Other
{
public void ShowSlotData()
{
Console.WriteLine("Other code displays data in thread_{0}'s data slot: {1,3}",
AppDomain.GetCurrentThreadId().ToString(),
Thread.GetData(
Thread.GetNamedDataSlot("Random")).ToString());
}
}
}
结果:
Other code displays data in thread_{0}'s data slot: 199
Other code displays data in thread_{0}'s data slot: 119
Other code displays data in thread_{0}'s data slot: 36
Other code displays data in thread_{0}'s data slot: 98
以上实例演示了 线程的创建,睡眠以及SetData()和GetData()方法的运用。
其中newThreads[i] = new Thread(Slot.SlotTest);也可以写作:
newThreads[i] = new Thread( new ThreadStart(Slot.SlotTest));
这两种写法的效果是一样的。都是创建一个线程。前者只是 C# 的语法,编译时编译器会自动转换成第二种的形式。ThreadStart 是线程的入口,可以理解为一个函数指针,指向线程将要运行的函数。
线程委托
1、ThreadStart
ThreadStart 是多线程的委托,所委托的方法不能有输入参数,返回值为void。
static void Main(string[] args)
{
ThreadStart threadStart=new ThreadStart(Calculate);
Thread thread=new Thread(threadStart);
thread.Start();
}
public void Calculate()
{
double Diameter=0.5;
Console.Write("The Area Of Circle with a Diameter of {0} is {1}"Diameter,Diameter*Math.PI);
}
2、ParameterizedThreadStart
ParameterizedThreadStart的定义为void ParameterizedThreadStart(object state),使用这个委托定义的线程的启动函数可以接受一个输入参数,参数类型为object。object可以为一个类,进而达到传递多个参数的目的。
实例:
class AddParams
{
public int a, b;
public AddParams(int numb1, int numb2)
{
a = numb1;
b = numb2;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("***** Adding with Thread objects *****");
Console.WriteLine("ID of thread in Main(): {0}",
Thread.CurrentThread.ManagedThreadId);
AddParams ap = new AddParams(10, 10);
Thread t = new Thread(new ParameterizedThreadStart(Add));
t.Start(ap);
Console.ReadLine();
}
#region Add method
static void Add(object data)
{
if (data is AddParams)
{
Console.WriteLine("ID of thread in Main(): {0}",
Thread.CurrentThread.ManagedThreadId);
AddParams ap = (AddParams)data;
Console.WriteLine("{0} + {1} is {2}",
ap.a, ap.b, ap.a + ap.b);
}
}
#endregion
}