多线程编程是跨语言的,跨环境的,所以我们得学好它,对应用程序的性能提高是有帮助的。
Thread类的使用
1.1 启动新的线程
Thread thread = new Thread(new ThreadStart(Count));Count是要被新的线程执行的函数,这个函数默认情况下是没有参数的。
1.2 杀死线程
在杀死一个线程前,先判断这个线程是否还活着(用IsAlive属性),如果它已经死掉了,就不要在杀死它了,那就成鞭尸了没有用的,如果它活着调用ABort方法来杀死此线程。
1.3 暂停线程
让一个运行的线程暂时停止运行即让一个正常运行的线程休眠一段时间,如:thread.sheep(1000)即让此线程休眠1秒钟。
1.4 优先级
每个线程是不一样的,它有优先级的,Thread 类中的ThreadPriority属性用来设置优先级,但是不能保证操作系统会接受此优先级,一个线程的优先级分为五种,Normal(正常的),AboveNormal(超过正常的),BelowNormal(低于正常的),Highest(最高的),Lowest(最低的)。
1.5 挂起线程
挂起线程是整个线程暂时停止了,挂起线程的整个暂停和暂停一个线程不一样,暂停一个线程是让一个正常运行的线程休眠一段时间,而挂起线程是把机子挂起来了,Thread类的Suspend方法用来挂起线程,直到调用Resume,此线程才能继续执行,如果线程被挂起了,当然就不会起作用了。
举个例子
比如你要抄腊肉,暂停线程相当于休息一会再炒腊肉,挂起线程就是把腊肉挂到墙上了,没得抄了,恢复线程相当于把墙上的腊肉拿下来炒了。
1.6 恢复线程
Resume用来恢复已经挂起的线程,让它继续执行,如果线程没被挂起,当然也不会起作用了。
举个例子
比如我控制5个机器人去探索月球,每个机器人相当于一个线程,每个机器人头上有4个按钮(启动新的线程,暂停线程,挂起线程,恢复线程),我按一下启动新的线程按钮,这个机器人就开始工作了,我按一下暂停线程,机器人就停止工作了,这5个机器人相当于5个线程,同时并发执行探索月球的,你可以通过每个机器人头上的按钮,同时控制这5个机器人也相当于同时控制5个线程了。
Thread
一个线程的方法是不带任何参数的,同时也不返回任何值的,它的命名规则和一般方法一样,可以是静态方法,也可以是非静态的方法,当这个方法执行完毕后,相应的线程也就结束了,这个线程的IsAlive属性也就被设置为flase了。
.NET的公共语言运行时(CLR)能区分两种不同类型的线程:即前台线程和后台线程,两者的区别是前台线程是应用程序必须运行完所有的前台线程才能退出,而对于后台线程而言,应用程序不考虑其是否已经运行完毕而直接退出,所有的后台线程在应用程序退出后,就都自动结束了。
默认情况下都是前台线程 IsBackground = false。
实现步骤
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
namespace _1_ThreadClassExample
{
class Program
{
public static void ThreadProcess()
{
for (int i = 0; i < 10; i++)
{
Console.WriteLine("ThreadProcess: {0}", i);
Thread.Sleep(0);//线程被阻塞的毫秒数,为0表示应挂起此线程以便其他等待线程能够执行
}
}
static void Main(string[] args)
{
Console.WriteLine("在主进程中启动一个线程");
Thread thread = new Thread(new ThreadStart(ThreadProcess));//创建一个线程
thread.Start();//启动此线程
Thread thread2 = new Thread(new ThreadStart(ThreadProcess));//创建一个线程
thread2.Start();//启动此线程
thread2.Suspend();//挂起此线程
for (int i = 0; i < 4; i++)
{
Console.WriteLine("主进程输出.....");
Thread.Sleep(0);//阻塞当前的主进程,执行别的进程,线程被阻塞的毫秒数,为0表示应挂起此线程以便其他等待线程能够执行
}
Console.WriteLine("主线程调用线程Join方法直到ThreadProcess1线程结束");
thread.Join();///阻塞调用线程,直到某个线程终止时为止
Console.WriteLine("ThreadProcess1线程结束");
thread2.Resume();//恢复挂起的线程
//thread2.IsBackground = true;
}
}
}
运行机制
在最开始输出了“主进程输出.....”,紧跟着输出了“ThreadProcess:1” ,又接着输出了“主进程输出.....”,然后紧跟着是“ThreadProcess:2””,又接着输出了“主进程输出.....”,然后紧跟着是“ThreadProcess:3””,它们交替出现,这是因为在for (int i = 0; i < 4; i++)中有句Thread.Sleep(0);的缘故,它的意思阻塞当前的主进程也就是Main这个主线程,执行别的进程,这个别的进程指的是thread这个进程也就是ThreadProcess()这个函数,在ThreadProcess()这个函数中也有句Thread.Sleep(0);它的意思同样也是阻塞当前的进程也就是thread这个进程,执行别的进程,这里别的线程指的是Main这个主线程,所以它俩交替出现,因为thread2这个线程被挂起了,所以暂时是不会执行的,因为这个线程(腊肠)被挂到墙上了,只有我们恢复这个线程(也就是从墙上取下这个腊肠才能炒它),这个线程才会执行的,thread.Join();的意思是阻塞调用线程,直到某个线程终止时为止,什么意思呢就是阻塞当前的主线程就是Main这个主线程,直到调用的线程也就是thread这个线程执行完毕,所以你会看到连着输出了“ThreadProcess:1”,“ThreadProcess:2”,,“ThreadProcess:3”等等直到,“ThreadProcess:9”,结束,紧接着我们写句thread2.Resume();恢复挂起的thread2这个线程,因为thread2这个线程执行的也是ThreadProcess()这个函数,所以最后你会看到连着输出了“ThreadProcess:1”,“ThreadProcess:2”,,“ThreadProcess:3”等等直到,“ThreadProcess:9”,结束。最后我们取消 thread2.IsBackground = true;这句代码的注释,虽然我们恢复了thread2这个线程,但是因为thread2.IsBackground = true,所以主线程不等它执行完毕就结束了,就没有继续输出“ThreadProcess:1”,“ThreadProcess:2”,,“ThreadProcess:3”等等直到9。
运行效果