使用C#编写任何程序时,都有一个入口:Main()方法。程序从Main()方法的第一条语句开始执行,直到这个方法返回为止。这样的程序结构非常适合于一个可识别的任务序列的程序,但程序常常需要同时完成多个任务。例如在使用文字处理软件的时候,用户在输入文字的同时,软件能同步进行拼写检查而不需要用记的等待;再如在一个应用程序的打印功能中,如果程序只能执行一个任务序列,用户可能需要等待所有的打印任务完成后才能继续操作,这时就需要能让程序同时处理多个任务的能力。
在上面的示例中提到的拼写检查和打印功能说明了应用程序需要处理多个任务的情形,所以最明显的解决方案是给应用程序提供多个执行线程。线程表示计算机执行的指令序列,从Windows 95操作系统开始引入了多线程机制,应用程序可以同时执行多个任务序列。每次创建一个新执行线程时,都需要指定从哪个方法开始执行。
在C#应用程序中,第一个线程总是Main()方法,因为第一个线程是由.NET运行库开始执行的,Main()方法是.NET运行库选择的第一个方法。后续的线程由应用程序在内部启动,即应用程序可以创建和启动新的线程。
1、多线程工作方式
一个处理器在某一刻只能处理一个任务,对于一个多处理器系统,理论上它可以同时执行多个指令——每个处理器执行一个指令,但大多数人使用的是单处理器计算机,同时执行多个指令的情况是不可能发生的。表面上Windwos操作系统上可以同时处理多个任务,这个过程称为抢先式多任务处理,所谓抢先式多任务处理,是指Windwos在某个进程中选择一个线程,该线程运行一小段时间。这个时间非常短,不会超过几毫秒。这段很短的时候称为线程的时间片。过了这个时间片后,Windows就收回控制权,选择下一个被分配了时间片的线程。这些时间非常短,我们可以认为许多事件是同时发生的。
即使应用程序只有一个线程,抢先式多任务处理的进行也在进行,因为系统上运行了许多其他进程,每个进程都需要一定的时间片来完成其线程。当屏幕上有许多应用程序窗口时,每个窗口都代表不同的进程,可以单击它们中的任一个,让它显示响应。这种响应不是即时的,在相关进程中下一个负责处理该窗口的用户输入的线程得到一个时间片时,这种响应才会发生。如果系统非常忙,就需要等待,但这种等待的时间非常短暂,用户不会察觉到。
2、什么时候使用多线程
应用多线程技术最大的误区在于没有分清适用的情况就盲目地使用多线程。除非运行一个多处理器计算机,否则在CPU密集的任务中使用两个线程不能节省多少时间,理解这一点是很重要的。在单处理器计算机上,让两个线程式同时进行100万次运算所花的时间与让一个线程进行200万次运算是相同的,甚至使用两个线程式所用的时间会略长,因为要处理另一个线程,操作系统必须用一定的时间切换线程,但这种区别可以忽略不计。使用线程带来的负面因素是必须额外考虑线程的并发、同步等线程安全问题,从而使得程序更加复杂而难以维护。
有些场合则使用多线程技术非常适合,如一个服务器进程需要并发处理来自不同客户端的访问。此外,使用多个线程的优点有两个。第一,可以及时对用户操作作出响应因为一个线程在处理用户输入时,另一个线程在后台完成其他工作,本章开始时所举的拼写检查和打印的例子就是风华正茂的适合多线程技术的应用;第二,如果一个或多个线程所处理的工作不占用CPU时间时,就可以节省时间,比如在经常使用多线程技术的网络应用开发中,让一个线程等待从Internet中获取数据,同时其他线程可以继续处理其他的任务。
|