C# 创建线程的多种方式之Thread类基础知识
1. Thread类创建线程
该类的构造函数可以接受ThreadStart委托参数(定义了无参,返回void的函数),以及ParameterizedThreadStart委托参数(定义了Object参数,返回void的函数)。
static void Main(string[] args) { Console.WriteLine("Main Start...."); Thread t1 = new Thread(Calculate); t1.Start(10); Console.WriteLine("Main is over"); Console.ReadLine(); } private static void Calculate(object obj) { int sum = 0; int total = (int)obj; for (int i = 0; i < total;i++ ) { sum += i; Thread.Sleep(100); } Console.WriteLine("Sum is "+sum); }
当然Thread类也可以和Lamda表达式一起使用,实现与上面同样的功能:
static void Main(string[] args) { Console.WriteLine("Main Start...."); Thread t1 = new Thread((obj) => { int sum = 0; int total = (int)obj; for (int i = 0; i < total; i++) { sum += i; Thread.Sleep(100); } Console.WriteLine("Sum is " + sum); }); t1.Start(10); Console.WriteLine("Main is over"); Console.ReadLine(); }
2. 后台线程
只要有一个前台在运行,应用进程就不会停止运行,而后台线程的运行则不会影响应用进程的结束,前,后台线程在线程优先级及其他方面并无差异。在默认情况下,Thread类创建的线程都是前台线程,也可以通过设置IsBackground属性改变为后台线程,而线程池创建的均为后台线程。如下,将Console.ReadLine();指令禁用,运行发现控制台窗体不会马上消失,而是会等待t1线程运行结束。
static void Main(string[] args) { Console.WriteLine("Main Start...."); Thread t1 = new Thread((obj) => { int sum = 0; int total = (int)obj; for (int i = 0; i < total; i++) { sum += i; Thread.Sleep(100); } Console.WriteLine("Sum is " + sum); }); t1.Start(10); Console.WriteLine("Main is over"); //Console.ReadLine(); }
3. 线程优先级
线程优先级用Priority属性表示,定义的级别有Highest, AboveNormal, BelowNormal, Lowest, 操作系统会根据优先级去调度线程。如果有优先级相同的几个线程在运行,就用得上时间量和循环的规则。如果线程是CPU密集型的(一直需要CPU不等待的),其优先级就低于定义的基本优先级。
4.线程的控制及状态
ThreadState 为线程定义了一组所有可能的执行状态。一旦线程被创建,它就至少处于其中一个状态中,直到终止。因为是各种状态的组合,所以在判断当前线程状态的时候就需要用位运算,而不能简单的使用等号(有个例外,Runing状态值为0,所以用与运算不行)。
Unstarted : 创建线程,但为调用Run();
Runing: 调用Run()后,当线程正在被CPU调用;
WaitSleepJoin:线程等待,调用Sleep(), Join()会进入该状态,其中Join()会阻塞当前线程,直到被调用线程运行结束或中止;
Stopped:线程运行结束后,进入该状态,该状态下无法通过Start(),重新启动线程,必须重新创建线程;
Background:当线程的IsBackground属性设置为true后,创建线程后调用线程前,状态为Unstarted+Background,而调用线程后状态为Runing+Background,sleep()后状态为WaitSleepJoin+Background,线程结束后状态为Stopped;
AbortRequested:当线程调用Abort(),处理完ThreadAbortException前,此时可以调用ResetAbort(),取消中止操作;
Aborted:当线程调用Abort(),处理完ThreadAbortException后;
SuspendRequested:当线程调用Suspend()后,线程被挂起前;
Suspended:线程已经被挂起,此时可用Resume(),继续运行;
控制线程的常用函数在上面基本上已经提到,其中Suspend(), Resume()已经不推荐使用,因为线程挂起可能会造成一些不可预知的问题,例如线程死锁,可以使用线程同步的一些类来代替使用。另外,Abort()也是不推荐使用的,可以定义布尔状态量来代替使用。Interrupt()上面未提到,调用这个函数后,会出现InterruptException,接着唤醒处于WaitSleepJoin状态的线程。