C#多线程
线程,被定义为程序的执行路径,每个线程都定主了一个独特的控制流。如果程序涉及到复杂和耗时的操作,那么把它们使用多线程来处理是可以提高执行效率的。
-
线程的生命周期
初始状态:未启动状态,当线程实例被创建但Start方法未被调用时的状态
就绪状态:当线程准备好运行并等待CPU周期时的状态
不可运行状态:有如下几种情况是不可运行的
1.已经调用Sleep方法
2.已经调用Wait方法
3.通过I/O操作阻塞
死亡状态:当线程已完成执行或已中止时的状态 -
主线程
C#中,System.Threading.Thread类用于线程的工作。它允许创建并访问多线程应用程序中的单个线 程。进程中一个被执行的线程称为主线程
当C#的程序开始执行时,主线程会自动创建。
使用Thread类创建的线程被主线程的子线程调用。
可以使用Thread类的CurrentThread属性访问线程。
使用Visual Studio新建C#控制台应用程序chapter25_001
在生成的工程Main方法中添加如下代码
//th对象中存放的是当前主线程
Thread th = Thread.CurrentThread;
th.Name = "Main";
Console.WriteLine("当前线程名称:{0}", th.Name);
Console.ReadKey();
编译运行结果如下:
-
Thread类常用属性
CurrentContext:获取线程正在其中执行的当前上下文
CurrentCulture:获取或设置当前线程的区域性
CurrentPrinciple:获取或设置线程的当前负责人
CurrentThread:获取当前正在运行的线程
CurrentUICulture:获取或设置资源管理器使用的当前区域性以便在运行时查找区域特定的资源
ExecutionContext:获取ExecutionContext对象,这个对象包含有关当前线程的各种上下文的信息
isAlive:获取一个值,这个值表示当前线程的执行状态
isBackground:获取或设围起一个值,这个值指示某个线程是否为后台线程
isThreadPoolThread:获取一个值,这个值指示线程是否属于托管线程池
ManagedThread:获取当前托管线程的唯一标识符
Name:获取或设置线程的名称
Priority:获取或设置一个值,这个值指示线程的调度优先级
ThreadState:获取一个值,这个值包含当前线程的状态 -
Thread类的常用方法
public void Abort(); 调用这个方法的线程引发ThreadAbortException,以开始终止这个线程的过程,调用这个方法一般会终止线程。
public static LocalDataStoreSlot AllocateDataSlot(); 在所有线程上分配未命名的数据槽。
public static LocalDataStoreSlot AllocateNamedDataSlot(string name); 在所有线程上分配已命名的数所槽
public static void BeginCriticalRegion(); 通知主机执行将要进入一个代码区域 ,在这个代码区域内线程中止或未经处理的异常的影响可能会危害应用程序区域中的其他任务
public static void BeginThreadAffinity(); 通知主机托管代码将要执行依赖于当前物理操作系统线程的标识指令
public static void EndCriticalRegion(); 通知主机执行将要进入一个代码区域 ,在这个代码区域内线程中止或未经处理的异常的影响可能会危害应用程序区域中的其他任务
public static void EndThreadAffinity(); 通知主机托管代码已执行完依赖于当前物流操作系统的标识指令
public static void FreeNameDataSlot(string name); 为进程中的所有线程消除名称与槽之间的关联
public static object GetData(LocalDataStoreSlot slot); 在当前线程的当前域中从当前线程上指定的槽中检索值
public static AppDomain GetDomain(); 返回当前线程正在其中运行的当前域
public static AppDomain GetDomainID(); 返回唯一的应用程序域标识符
public static LocalDataStoreSlot GetNamedDataSlot(string name); 查找已命名的数据槽
public void Interrupt(); 中断处于 WaitSleepJoin 线程状态的线程
public void Join(); 在继续执行标准的 COM 和 SendMessage 消息泵处理期间,阻塞调用线程,直到某个线程终止为止
public static void MemoryBarrier(); 按如下方式同步内存存取:执行当前线程的处理器在对指令重新排序时,不能采用先执行 MemoryBarrier 调用之后的内存存取,再执行 MemoryBarrier 调用之前的内存存取的方式
public static void ResetAbort(); 取消为当前线程请求的 Abort
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 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 ); 读取字段值
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 ); 立即向字段写入一个值,以使该值对计算机中的所有处理器都可见
public static bool Yield(); 导致调用线程执行准备好在当前处理器上运行的另一个线程 -
创建线程
线程是通过扩展Thread类创建的,扩展的Thread类调用Start()方法来开始子线程的执行。
使用Visual Studio新建C#控制台应用程序
public static void CallToChildThread()
{
Console.WriteLine("子线程开始执行!");
}
static void Main(string[] args)
{
Console.WriteLine("在Main方法中创建子线程!");
//这里使用了委托
ThreadStart childref = new ThreadStart(CallToChildThread);
Thread ChildThread = new Thread(childref);
//开始执行子线程
ChildThread.Start();
Console.ReadKey();
}
编译运行的结果如下:
- 管理线程
Thread类提供了各种管理线程的方法,比如Sleep()方法,用于在一个特定的时间暂停线程。
使用Visual Studio新建C#控制台应用程序chapter25_002
在生成工程中添加如下代码
public static void CallToChildthread()
{
Console.WriteLine("子线程启动!");
//把线程暂挺2000毫秒
int sleep_time = 2000;
Console.WriteLine("子线程暂停{0}秒", sleep_time / 1000);
Thread.Sleep(sleep_time);
Console.WriteLine("子线程继续执行!");
}
static void Main(string[] args)
{
ThreadStart childref = new ThreadStart(CallToChildthread);
Console.WriteLine("在Main中创建子线程");
Thread childThread = new Thread(childref);
childThread.Start();
Console.ReadKey();
}
}
编译运行结果
当执行输出“子线程暂停2秒”这个语句时,子线程会停止2秒后再继续向下执行。
- 销毁线程
使用Abort()方法可以销毁线程,并且这个方会引发ThreadAbortException异常