引言:程序员
最近一段时间都在研究关于.Net线程的内容,以为线程是每一个程序员都应该掌握的,因此写下这个线程的系列但愿能给你们学习过程当中一些帮助,同时也是本身对线程的巩固,当中若是有什么错漏还请你们指出,这样咱们能够互相获得进步。编程
目录:多线程
1、线程的介绍异步
2、线程调度和优先级ide
3、前台线程和后台线程学习
4、简单线程的使用spa
1、线程的介绍操作系统
在介绍线程以前, 颇有必要知道什么是进程,以及与线程的关系。.net
进程(Process)是应用程序的实例要使用的资源的一个集合(从能够简化理解:进程就是一种资源,是应用程序所用的资源)。每一个应用程序都在各自的进程中运行来确保应用程序不受其余应用程序的影响,若是一个应用程序失败了, 只会影响本身的进程,其余进程中的应用程序能够继续运行。进程是操做系统为咱们提供的一种保护应用程序的一种机制。线程
线程是进程中基本执行单元, 一个进程中能够包含多个线程,在进程入口执行的第一个线程是一个进程的主线程,在.Net应用程序中,都是以Main()方法做为程序的入口的, 因此在程序运行过程当中调用这个方法时,系统就会自动建立一个主线程。(他们之间的关系简单说:线程是进程的执行单元,进程是线程的一个容器了)。
2、线程调度和优先级
Windows之因此被称为抢占式多线程操做系统,是由于线程能够在任意时间被抢占,并调度另外一个线程。每一个线程都分配了从0~31的一个优先级。系统首先把高优先级的线程分配给CPU执行。Windows 支持7个相对线程优先级:Idle,Lowest,Below Normal,Normal,Above Normal,Highest和Time-Critical,Normal是默认的线程优先级,然而在程序中能够经过设置Thread的Priority属性来改变线程的优先级,它的类型为ThreadPriority枚举类型,包含枚举有:Lowest,BelowNormal,Normal,AboveNormal和Highest,CLR为本身保留了 Idle和Time-Critical优先级。具体每一个枚举值含义以下表:
成员名称 | 说明 |
---|---|
Lowest | 能够将 Thread何其余优先级的线程以后。 |
BelowNormal | 能够将 Thread Normal 优先级的线程以后,在具备 Lowest 优先级的线程以前。 |
Normal | 能够将 Thread AboveNormal 优先级的线程以后,在具备 BelowNormal 优先级的线程以前。 默认状况下,线程具备 Normal 优先级。 |
AboveNormal | 能够将 Thread Highest 优先级的线程以后,在具备 Normal 优先级的线程以前。 |
Highest | 能够将 Thread 其余优先级的线程以前。 |
3、前台线程和后台线程
在.net中线程分为前台线程和后台线程,在一个进程中,当全部前台线程中止运行时,CLR会强制结束仍在运行的任何后台线程,这些后台线程直接被终止,不会抛出异常。
因此咱们应该在前台线程中执行咱们确实要完成的事情,另外, 应该把非关键的任务使用后台线程,咱们用Thread建立的是线程为前台线程。让咱们经过下面的一段代码来看看前台线程和后台线成的区别:
using System; using System.Threading; class Program { static void Main(string[] args) { // 建立一个新线程(默认为前台线程) Thread backthread = new Thread(Worker); // 使线程成为一个后台线程 backthread.IsBackground = true; // 经过Start方法启动线程 backthread.Start(); // 若是backthread是前台线程,则应用程序大约5秒后才终止 // 若是backthread是后台线程,则应用程序当即终止 Console.WriteLine("Return from Main Thread"); } private static void Worker() { // 模拟作10秒 Thread.Sleep(5000); // 下面语句,只有由一个前台线程执行时,才会显示出来 Console.WriteLine("Return from Worker Thread"); } }
运行上面代码能够发现:控制台中显示字符串: Return form Main Thread 后就退出了, 字符串 Return from Worker Thread字符串根本就没有显示,这是由于此时的backthread线程为后台线程,当主线程(执行Main方法的线程,主线程固然也是前台线程了)结束运行后,CLR会强制终止后台线程的运行,整个进程就被销毁了,并不会等待后台线程运行完后才销毁。若是把 backthread.IsBackground = true; 注释掉后, 就能够看到控制台过5秒后就输出 Return from Worker Thread。再在Worker方法最后加一句 代码:Console.Read(); 就能够看到这样的结果了:
注意:有些人可能会问我不想把 backthread.IsBackground = true;注释掉, 又想把Worker()方法中的字符串输出在控制台上怎么作呢? 实际上是有解决的办法的, 咱们能够调用thread.Join()方法来实现,Join()方法能保证主线程(前台线程)在异步线程thread(后台线程)运行结束后才会运行。
实现代码以下:
using System; using System.Threading; class Program { static void Main(string[] args) { // 建立一个新线程(默认为前台线程) Thread backthread = new Thread(Worker); // 使线程成为一个后台线程 backthread.IsBackground = true; // 经过Start方法启动线程 backthread.Start(); backthread.Join(); // 模拟主线程的输出 Thread.Sleep(2000); Console.WriteLine("Return from Main Thread"); Console.Read(); } private static void Worker() { // 模拟作3秒 Thread.Sleep(3000); // 下面语句,只有由一个前台线程执行时,才会显示出来 Console.WriteLine("Return from Worker Thread"); } }
运行结果(调用Join方法后后台线程会阻塞主线程因此主线程会后输出):
4、简单线程的使用
其实在上面介绍前台线程和后台线程的时候已经经过ThreadStart委托建立了一个线程了,此时已经实现了一个多线程的一个过程,为此系列中将多线程也是作一个铺垫吧。下面经过ParameterizedThreadStart委托的方式来实现多线程。
以ParameterizedThreadStart委托的方式来实现多线程:
using System; using System.Threading; class Program { static void Main(string[] args) { // 建立一个新线程(默认为前台线程) Thread backthread = new Thread(new ParameterizedThreadStart(Worker)); // 经过Start方法启动线程 backthread.Start("123"); // 若是backthread是前台线程,则应用程序大约5秒后才终止 // 若是backthread是后台线程,则应用程序当即终止 Console.WriteLine("Return from Main Thread"); } private static void Worker(object data) { // 模拟作5秒 Thread.Sleep(5000); // 下面语句,只有由一个前台线程执行时,才会显示出来 Console.WriteLine(data + " Return from Worker Thread"); Console.Read(); } }
注意:此时Worker方法传入了一个参数,而且Start方法也传递了一个字符传参数。 对比与以前建立Thread的不一样,
运行结果为:
写到这里, 本系列的第一篇差很少讲完了,在后续的文章将会介绍Thread方法的使用以及经过一些例子来展现他们的不一样之处(像Abort()方法Interrupt方法等)对于线程的一些高级使用(如线程池,并行编程和PLINQ、线程同步和计时器)都会在后续中讲到。