C# 多线程详解Thread

所需积分/C币:11 2018-11-17 11:52:20 216KB PDF

多线程的好处在于可以提高CPU 的利用率——任何一个程序员都不希望自己的程序很多 时候没事可干,在多线程程序中,一个线程必须等待的时候,CPU 可以运行其它的线程而不是 等待,这样就大大提高了程序的效率。
们使用了如下命名空间: using sy stem; using System. Threading 在. net framework class library中,所有与多线程机制应用相关的类都是放在 System. Threading命名空间中的。其中提供 Thread类用于创建线程, ThreadPool类用于管 理线程池等等,此外还提供解决了统程执行安排,死锁,线程冏通讯奐际冋懃的杋制。如 果你翘在你的应用程序中使用多线程,就必须包含这个类。 Thread类有几个至关重要的方法, 描述如下 Start(:启动线程 Sleep(int):静态方法,暂停当前线程指定的亳秒数 Abort o:通常使用该方法来终止一个线程 Suspend○:该方法并不终止未完成的线程,它仅仅挂起线程,以后还可恢复。 Resume:恢复被 Suspend○方法挂起的线程的执行 下面我仉就动手来创建一个线程,使用 Thread类创建线程时,只卿提供线程入口即可。线程 入口使程序知道该让这个线程干什么事,在C中,线程入口是通过 Threadstart代理 ( delegate)来提供的,你可以把 Threadstart理解为一个函数指针,指向线程要执行的函 数,当调用 hread. Start(方法后,线程就开始执行' headstart所代表或者说指向的函数。 打开你的VS.net,新建一个控制台应用程序( Console application),下面这些代码将 让你体味到完全控制一个线程的无穷乐趣! //ThreadTest cs using System; using System. Threading namespace Thread Test public class alpha public void Beta while (true) Console. Writeline( alpha. Beta is running in its own thread. public class simple public static int Maino Console. WriteLine( thread Start/Stop/ Join Sample") Alpha oAlpha new Alpha o file:/这里创建一个线程,使之执行 Alpha类的Beta()方法 Thread oThread= new Thread (new ThreadStart(oAl pha. Beta)) oThread Start hile (oThread. SaLi Thread. Sleep (1) oThread Abort o oThread. Join Console. WriteLineo Console. WriteLine( alpha. Beta has finished") try Console. Writeline( try to restart the Alpha. Beta thread") oThread Start o catch(ThrcadStatcException Console. Write( ThreadStateException trying to restart Alpha. Beta.) Console. WriteLine( Expected since aborted threads cannot be restarted.") Console. ReadLine o return O 这段程序包含两个类 Alpha和 Simple,在创建线程 oThread时我们用指向 Alpha.Beta0 方法的初始化了 ThreadStart代理( delegate)对象,当我们创建的线程 aThread调用 o Thread. Start(方法启动时,实际上程序运行的是 alpha. Beta方法: Alpha oAlpha new Alpha o Thread oThread= new Thread (new ThreadStart(oAlpha Beta)) oThread Start o 然后在Main(函数的 while循环中,我们使用静态方法 Thread. Sleep0让主线程停了1ms 这段时间C門U转向执行线程 o Thread然后我们试图用 Thread. Abort(方法终止线程 oThread, 注意后面的 oThread.Join(, Thread. Join o方法使主线程等待,直到 oThread线程结束。你 可以给 Thread. Join(方法指定一个int型的参数作为等待的最长时间。之后,我们试图用 Thread. Start方法重新启动线程 oThread,但是显然 Abort(方法带来的后果是不可恢复的 终止线程,所以最后程序会抛出 ThreadstateException异常。 程序最后得到的结果将如下图 F:isual Studio Projects\Consoleapplication\bin\Debug ThreadTest exe X lpha Beta is running in its own thread Alpha. Beta is running in its own thread Alpha. Beta is running in its own thread Alpha. Beta is running in its own thread Alpha. Beta is running in its own thread Alpha. Beta is running in its own thread Alpha. Beta is running in its own thread Alpha. Beta is running in its own thread Alpha. Beta is running in its own thread. Alpha.Beta is running in its own thread Alpha. Beta is running in its own thread lpha Beta is running in its own thread Alpha. Beta is running in its own thread Alpha. Beta is running in its own thread Ipha Heta is running in its own thread lpha Beta is running in its own thread Alpha. Beta is running in its own thread Alpha. Beta is running in its own thread Alpha. Beta is running in its own thread Alpha. Beta has finished Try to restart the Alpha. Beta thread Threadstate Exception trying to restart Alpha. Beta. Expected since aborted thread s cannot be restarted 在这里我们要注意的是其它线程都是依附于Main(函数所在的线程的,Main(函数是C甘程序 的入口,起始线程可以称之为主线程,如果所有的前台线程都伃止了,那么主线程可以终止, 而所有的后台线程都将无条件终止。而所有的线程虽然在微观上是串行执行的,但是在宏观 上你完全可以认为它们在并行执行。 读者一定注到了 Thread. Thrcadstate这个属性,这个属性代表了线程运行时状态,在 不同的情况下有不同的值,于是歌们有时候可以逦过对该值的判斷来设讣程序流程。 Threadstate在各种情况下的可能取值如下; Aborted:线程已停止 AbortRequested:线程的 Thread. Abort(方法已被调用,但是线程还未停止 Background:线程在后台执行,与属性 Thread. BaCkground有关 Running:线程正在正常运行 Stopped:线程己经被停止 StopRequested:线程正在被要求停止 Suspended:线程已经被挂起(此状态下,可以通过调用 Resume(方法重新运行) SuspendRequested:线程正在要求被挂起,但是未来得及响应 Unstarted:木调用 Thread. Start(开始线程的运行 Waitsleep. Join:线程因为调用了 Wait(, Sleep(或Join等方法处于封锁状恋 上面提刭了 Background状态表示该线程在后台运行,那么后台运行的线程有什么特别的 地方呢?其实后台线程跟前台线程只冇一个区別,那就是后台线程不妨碍程序的终止。一与 一个进程所有的前台线程都终止后,CLR(通用语言运行环境)将通过调用任意一个存活中的 后台进程的 Abort(方法來彻底终止进程。 当线程之间爭夺CPU时间时,CPU按照是线程的优先級给予服务的。在C#应用程序中, 用户可以设定5个不同的优先级,由高到低分别是 Highest, AboveNormal, Normal, Below normal, Lowest,在创建线程时如果不指定优先级,那么系统默认为 ThreadPriority. orma l。给一个 线程指定优先級 我们可以使用如下代码: 设定优先级为最低 my Thread Priority=ThreadPriority Lowest 通过设定线程的优先级,我们可以安排一些相对重要的线程优先执行,例如对用户的响 应普等。 现在我仉对怎样创建和控制一个线程已经有了一个初步的了解,下面我们将深入研究线 程实现中比较典型的的问题,并且探讨其解决方汯。 线程的同步和通讯一一生产者和消费者 没这样一种情祝,两个线程冋时维护一个队列,如果一个线程对队列中添加元素,而 另外一个线程从队列中取用元索,那么我们称添加元素的线程为生产者,称取用元素的线程 为消费者ε生产者与消费者问题看起来很苘单,但是却是珍线程应用中一个必须解决的川题, 它涉及到线程之间的同步和通讯同题。 前面说过,每个线程都有白已的资源,但是代码区是共享的,即每个线程都可以执行相 同的函数。但是珍线程环境下,可能带來的冋题就是几个线程同时执行一个函数,导致教据 的混乱,产生不可预料的结果,因此我们必须避免这种情况的发生。C#提供了一个关键字lock, 它可以把一段代码定义为互斥段( critical section),互斥段在一个时刻内只允许一个线程 选入执行,而其他线程必须哿侍。在C#中,关键字lock定义如下 lock(expression) statement block expression代表你希望跟踪的对象,通常是对象引用。一般地,如果你靚保护一个类的实例 你可以使用this;如果你希望保护一↑棦态变量(如互斥代码段在一个静恋方法内部),一般 使用类名就可以了。而 statement block就是互斥段的代码,这段代码在一个时刻内只可能 被一个线程执行。 下面是一个使用10ck关键字的典型例子,我将在注释里向大家说明lock关键字的用法 和用途: /lock. cs using System using System. Threading internal class account t balance Random r= new Random o internal Account(int initial balance initial internal int Withdraw(int amount) if (balance < 0 file://如果 balance小于0则抛出异常 throw new Exception (Negative Balance") /下面的代码保证在当前线程修改 balance的值完成之前 //不会有其他线程也执行这段代码来修改 balance的值 /因此, balance的值是不可能小于0的 lock (this) Console. WriteLine( Current Thread: +Thread. Current Thread Name) file://如果没有lock关键字的保护,那么可能在执行完if的条件判断之后 file://另外一个线程却执行了 balance- balance- amoun t修改了 balance的值 file:/而这个修改对这个线程是不可见的,所以可能导致这时if的条件已经不成 立了 file://但是,这↑线程却继续执行 balance- balance- amount,所以导致balaηce可 能小于0 if (balance >=amount Thread. Sleep(5) balance= balance-amount return amount return 0;// transaction rejected internal void Dotransactions( for (int i=0:i< 100 Withdraw(r Next(-50, 100)) nternal class Test static internal Thread threads new Thread 10 public static void Main() Account acc new Account (O) for (int i i<10;i++) Thread t= new Thread (new ThreadStart(acc DoTransactions)) threads[i= t: for (int i=0:i<10: i++) threadsLi]. Name-i. ToStringo (inti=0;i<10;i+) reads li start o Console. ReadLineo 而多线程公用一个对象时,也会出现和公用代码类似的问题,这种问题就不应该使用1ock 关键字了,这里需要用到 Systel. Threading中的一个类 Monitor,我们可以称之为监视器, Monitor提供了使线程共亨资源的方案。 Monitor类可以锁定一个对象,一个线程只有得到这把锁寸可以对该对象进行操作。对象 锁机制保证了在可能引起混乱的情况下一个时划只有一个线程可以访问这个对象。 Monitor必 须和一个具体的对象相头联,但是由于它是一个静态的类,所以不能使用它来定义对象,而 且它的所有方法都是静恋的,不能使用对象来引用。下面代码说明了使用 Monitor锁定一

...展开详情
img
smhastydl

关注 私信 TA的资源

上传资源赚积分,得勋章
最新资源