C#线程的生命周期分为几个阶段:
一、未启动状态:当线程实例被建立但 Start 方法未被调用时的情况;
二、就绪状态:当线程准备好运行并等待 CPU 周期时的情况;
三、不可运行状态:下面的几种状况下线程是不可运行的:
1). 已经调用 Sleep 方法;
2). 已经调用 Wait 方法;
3). 经过 I/O 操做阻塞。
四、死亡状态:当线程已完成执行或已停止时的情况。异步
一个简单的不带参数的线程:函数
//线程函数 public static void Task() { for (int i = 0; i < 10; i++) { Console.WriteLine("Task Print {0}", i); Thread.Sleep(1000); } } //建立简单的线程,不带任何参数 Thread th = new Thread(Task); th.Name = "PrintThread"; //启动执行线程 th.Start(); //等待线程执行完毕 th.Join(); Console.WriteLine("Thread [{0}] Finished !", th.Name);
对于带参数的线程方法,一般须要自定义一个线程参数类,示例:线程
//自定义的线程参数类 class ThreadParameter { private int size; public ThreadParameter(int s) { size = s; } //线程方法 public void ThreadMethod() { for (int i = 0; i < size; i++) { Console.WriteLine("Task1 Print {0}", i); Thread.Sleep(1000); } } } //实例化线程参数类 ThreadParameter tp = new ThreadParameter(10); //实例化线程对象 Thread th = new Thread(tp.ThreadMethod); th.Name = "PrintThread"; //启动线程 th.Start(); //等待线程结束 th.Join(); Console.WriteLine("Thread [{0}] Finished !", th.Name);
Abort() 方法用于销毁线程。经过抛出 threadabortexception 在运行时停止线程。这个异常不能被捕获,若是有 finally 块,控制会被送至 finally 块。code
public static void ThreadProc() { try { for (int i = 0; i < 10; i++) { Console.WriteLine("Task1 Print {0}", i); Thread.Sleep(1000); } } //捕获线程异常退出 catch (ThreadAbortException e) { Console.WriteLine(e); } finally { Console.WriteLine("Thread Finished !"); } } //实例化线程对象 Thread th = new Thread(ThreadProc); //启动线程 th.Start(); //等待5秒后结束线程 Thread.Sleep(5000); th.Abort(); Console.WriteLine("Thread [{0}] Finished !", th.Name);
有时候一个函数的执行很长,不能一直等待函数执行完毕,但愿在函数执行的时候主线程能够完成些其余的事情,而后再等待线程执行完毕。下面的代码同步执行时会依次打印1~5数字,而异步执行的时候则是乱序的:orm
static void Test(string name) { Console.WriteLine("TestMethod: {0:yyyy-MM-dd HH:mm:ss.fff} {1}", DateTime.Now, name); } static void Main() { TestDelegate d = Test; Console.WriteLine("Beginning : {0:yyyy-MM-dd HH:mm:ss.fff}", DateTime.Now); //同步执行,依次打印 d("111"); d("222"); d("333"); d("444"); d("555"); //异步执行,会放入线程池中,打印乱序 var r1 = d.BeginInvoke("小明1", null, null); var r2 = d.BeginInvoke("小明2", null, null); var r3 = d.BeginInvoke("小明3", null, null); var r4 = d.BeginInvoke("小明4", null, null); var r5 = d.BeginInvoke("小明5", null, null); //此时异步执行尚未完成 Console.WriteLine("End : {0:yyyy-MM-dd HH:mm:ss.fff}", DateTime.Now); //等待异步执行完成 d.EndInvoke(r1); d.EndInvoke(r2); d.EndInvoke(r3); d.EndInvoke(r4); d.EndInvoke(r5); Console.WriteLine("线程所有执行完成"); Console.Read(); }
另一个定时器定时打印的例子:对象
//打印当前日期和时间 static void PrintPoint(object sender, ElapsedEventArgs e) { DateTime dtCurr = DateTime.Now; Console.WriteLine("{0:yyyy-MM-dd HH:mm:ss.fff}", dtCurr); Thread.Sleep(1000); } static void Main() { //构建定时器, System.Timers.Timer timer = new System.Timers.Timer(); timer.Interval = 1000; timer.Start(); //链接打印方式到定时器超时事件 timer.Elapsed += new ElapsedEventHandler(PrintPoint); Console.WriteLine("End"); Console.Read(); }
在主线程中使用EndInvoke仍是很麻烦,始终要阻塞等待。使用异步回调就能够解决这个问题,当异步返回时自动调用回调函数:生命周期
//异步结束时的回调 public static void BackCall(IAsyncResult parameter) { //parameter.IsCompleted用于判断异步方法是否已调用完成; if (parameter.IsCompleted) { //经过EndInvoke方法获取异步方法的返回结果(类型与异步方法的结果一致) Console.Write(string.Format("回调完成,返回值")); } else { Console.Write("调用未完成"); } } TestDelegate td = PrintPoint; td.BeginInvoke(BackCall, null); Console.WriteLine("End"); Console.Read();