C#中的多线程编程.doc
《C#中的多线程编程.doc》由会员分享,可在线阅读,更多相关《C#中的多线程编程.doc(9页珍藏版)》请在淘文阁 - 分享文档赚钱的网站上搜索。
1、C#中的多线程编程 C#是.Net平台的通用开发工具,它能够建造所有的.Net应用。在.Net中所有线程都运行在应用程序域(AppDomain)中,这也许让你想到Win32进程,实际上它们还是有很大的不同。应用程序域提供了一种安全而通用的处理单元,公共语言运行库可使用它来隔离应用程序。注意在.Net中应用程序的隔离是应用程序域而不是进程,在单个进程中可以存在几个应用程序域,而且线程可以跨越应用程序域的范围,某个线程中的方法可以调用另一个线程的方法,这样的话就不会造成进程间调用或进程间切换等方面的额外开销。可以说应用程序域是物理进程(也即win32中的Process)内的逻辑进程。在VisulC
2、#中System.Threading命名空间提供一些使得可以进行多线程编程的类和接口,其中线程的创建有以下三种方法:Thread、ThreadPool、Timer。下面我就它们的使用方法逐个作一简单介绍。1Thread这也许是最复杂的方法,但它提供了对线程的各种灵活控制。首先你必须使用它的构造函数创建一个线程实例,它的参数比较简单,只有一个ThreadStart委托:C#publicThread(ThreadStartstart);然后调用Start()启动它,当然你可以利用它的Priority属性来设置或获得它的运行优先级(enumThreadPriority:Normal、Lowest、H
3、ighest、BelowNormal、AboveNormal)。见下例:它首先生成了两个线程实例t1和t2,然后分别设置它们的优先级,接着启动两线程(两线程基本一样,只不过它们输出不一样,t1为“1”,t2为“2”,根据它们各自输出字符个数比可大致看出它们占用CPU时间之比,这也反映出了它们各自的优先级)。staticvoidMain(stringargs)Threadt1=newThread(newThreadStart(Thread1);Threadt2=newThread(newThreadStart(Thread2);t1.Priority=ThreadPriority.BelowNo
4、rmal;t2.Priority=ThreadPriority.Lowest;t1.Start();t2.Start();publicstaticvoidThread1()for(inti=1;i1000;i+)/每运行一个循环就写一个“1”dosth();Console.Write(1);publicstaticvoidThread2()for(inti=0;i1000;i+)/每运行一个循环就写一个“2”dosth();Console.Write(2);publicstaticvoiddosth()/用来模拟复杂运算for(intj=0;j10000000;j+)inta=15;a=a*a
5、*a*a;以上程序运行结果为:111111111111111111111111111111111111111111211111111111111111111111111111111111111111121111111111111111111111111111111111111111112111111111111111111111111111111111111111111211111111111111111111111111111111111111111121111111111111111111111111111111111111111112从以上结果我们可以看出,t1线程所占用CPU的时间远比
6、t2的多,这是因为t1的优先级比t2的高,若我们把t1和t2的优先级都设为Normal,那结果是如何?它们所占用的CPU时间会一样吗?是的,正如你所料,见下图:121211221212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212121212从上例我们可看出,它的构造类似于win32的工作线程,但更加简单,只需把线程要调用的函数作为委托,然后把委托作为参数构造线程实例
7、即可。当调用Start()启动后,便会调用相应的函数,从那函数第一行开始执行。接下来我们结合线程的ThreadState属性来了解线程的控制。ThreadState是一个枚举类型,它反映的是线程所处的状态。当一个Thread实例刚创建时,它的ThreadState是Unstarted;当此线程被调用Start()启动之后,它的ThreadState是Running;在此线程启动之后,如果想让它暂停(阻塞),可以调用Thread.Sleep()方法,它有两个重载方法(Sleep(int)、Sleep(Timespan)),只不过是表示时间量的格式不同而已,当在某线程内调用此函数时,它表示此线程将
8、阻塞一段时间(时间是由传递给Sleep的毫秒数或Timespan决定的,但若参数为0则表示挂起此线程以使其它线程能够执行,指定Infinite以无限期阻塞线程),此时它的ThreadState将变为WaitSleepJoin,另外值得注意一点的是Sleep()函数被定义为了static?!这也意味着它不能和某个线程实例结合起来用,也即不存在类似于t1.Sleep(10)的调用!正是如此,Sleep()函数只能由需“Sleep”的线程自己调用,不允许其它线程调用,正如whentoSleep是个人私事不能由它人决定。但是当某线程处于WaitSleepJoin状态而又不得不唤醒它时,可使用Threa
9、d.Interrupt方法,它将在线程上引发ThreadInterruptedException,下面我们先看一个例子(注意Sleep的调用方法):staticvoidMain(stringargs)Threadt1=newThread(newThreadStart(Thread1);t1.Start();t1.Interrupt();E.WaitOne();t1.Interrupt();t1.Join();Console.WriteLine(“t1isend”);staticAutoResetEventE=newAutoResetEvent(false);publicstaticvoidTh
10、read1()try/从参数可看出将导致休眠Thread.Sleep(Timeout.Infinite);catch(System.Threading.ThreadInterruptedExceptione)/中断处理程序Console.WriteLine(1stinterrupt);E.Set();try/休眠Thread.Sleep(Timeout.Infinite);catch(System.Threading.ThreadInterruptedExceptione)Console.WriteLine(2ndinterrupt);/暂停10秒Thread.Sleep(10000);运行结
11、果为:1stinterrupt2ndinterrupt(10s后)t1isend从上例我们可以看出Thread.Interrupt方法可以把程序从某个阻塞(WaitSleepJoin)状态唤醒进入对应的中断处理程序,然后继续往下执行(它的ThreadState也变为Running),此函数的使用必须注意以下几点:1.此方法不仅可唤醒由Sleep导致的阻塞,而且对一切可导致线程进入WaitSleepJoin状态的方法(如Wait和Join)都有效。如上例所示,使用时要把导致线程阻塞的方法放入try块内,并把相应的中断处理程序放入catch块内。2.对某一线程调用Interrupt,如它正处于Wa
12、itSleepJoin状态,则进入相应的中断处理程序执行,若此时它不处于WaitSleepJoin状态,则它后来进入此状态时,将被立即中断。若在中断前调用几次Interrupt,只有第一次调用有效,这正是上例我用同步的原因,这样才能确保第二次调用Interrupt在第一个中断后调用,否则的话可能导致第二次调用无效(若它在第一个中断前调用)。你可以把同步去掉试试,其结果很可能是:1stinterrupt上例还用了另外两个使线程进入WaitSleepJoin状态的方法:利用同步对象和Thread.Join方法。Join方法的使用比较简单,它表示在调用此方法的当前线程阻塞直至另一线程(此例中是t1)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- C# 中的 多线程 编程
限制150内