多线程

来源:互联网 发布:office mac 2010破解 编辑:程序博客网 时间:2024/06/07 17:42
什么是多线程?

多线程就是使程序并发(同时)执行几个操作。

.NET 框架类库在System.Threading 中加入了多线程的能力。因此要在前面加入引用 using System.Threading

Thread 类:创建并控制线程,设置其优先级并获取其状态。

Thread 类的构造方法,主要有2中:Thread thread_name=

Thread(ThreadStart):ThreadStart 委托,它表示此线程开始执行时要调用的方法。适用于无参数的方法。

Thread(ParameterizedThreadStart):ParameterizedThreadStart 委托,它表示此线程开始执行时要调用的方法。适用于有参数传入的方法。

一个普通的 无参 线程操作如下:

[csharp] view plaincopyprint?01.Thread td = new Thread(xunhuan);//定义一个线程,参数是一个方法,无返回值,采用的是委托02.03.//前台线程,所有的线程都执行完了,应用程序才退出,默认的都是前台线程04.//后台线程,所有的前台线程都执行完了,就退出,不管后台的线程05.td.IsBackground = true; //设定为后台线程06.td.Start();//启动线程Thread td = new Thread(xunhuan);//定义一个线程,参数是一个方法,无返回值,采用的是委托//前台线程,所有的线程都执行完了,应用程序才退出,默认的都是前台线程//后台线程,所有的前台线程都执行完了,就退出,不管后台的线程td.IsBackground = true; //设定为后台线程td.Start();//启动线程一个有参的线程如下:
[csharp] view plaincopyprint?01.Thread ptd = new Thread(showname);//定义个线程,传入的带参数的方法。02.ptd.IsBackground = true;03.ptd.Start("lilei");//重载Start方法,传递个参数Thread ptd = new Thread(showname);//定义个线程,传入的带参数的方法。ptd.IsBackground = true;ptd.Start("lilei");//重载Start方法,传递个参数有参的方法定义,参数objec类型,
[csharp] view plaincopyprint?01.//线程调用,带多个参数02. static void shownames(object names)03. {04. List list = names as List;05. foreach (string name in list)06. {07. MessageBox.Show(name);08. }09.10. }//线程调用,带多个参数static void shownames(object names){List list = names as List;foreach (string name in list){MessageBox.Show(name);}}------------------------------------------------------------------------线程的状态-----------------------------------------------------------------------任何时候,线程都要处于某种线程状态中。新线程在Unstarted状态中开始它的生命周期。在调用Thread类的Start方法之前,会一直保持在Unstarted状态,调用方法之后,就会进入Started状态,并立即将程序的控制权返回调用程序(点了线程调用后,可以立即去干别的事)。然后,调用了Start方法的线程(也就是Started线程)和程序中其他的线程并发执行。线程的优先级每个线程都有个优先级,其范围在ThreadPriority.Lowest和ThreadPriority.Highest之间。默认情况下,每个线程的优先级都是Normal。Windows操作系统支持时间分片(timeslicing)的概念,它的思路是优先级相同的线程共享一个处理器。------------------------------------------------------------------------线程的同步和类监视器-----------------------------------------------------------------------通常,多个执行线程要操作共享数据。如果有权访问共享数据的线程只能读取数据,那就不需要阻止多个线程同时访问共享数据。然而,当多个线程共享数据,并且其中一个或多个线程要修改数据时,可能会出现无法预知的结果。如果一个线程正在更新数据,另一个线程也试图更新,那么数据所反映的就第二次更新操作之后的结果。所以可通过一次只允许一个线程访问用于操作共享数据的代码来解决。其他想要操作数据的线程应该等待。具有排他访问权的线程完成对数据的操作后,等待操作线程的数据可以继续执行。这称为互斥或线程同步。C#提供了两中解决技术:1.Monitor类:主要方法(方法传入的参数为objec对象,一般为当前调用的线程):Monitor.Enter():获取排他锁。Monitor.Wait():释放对象上的锁并阻止当前线程,直到重新获取该锁。Monitor.Pulse():通知等待队列中的线程对象状态的改变。Monitor.Exit():释放排他锁。2.lock关键字:在对象前加个lock:代码示例:Monitor的用法:
[csharp] view plaincopyprint?01.public class mt02. {03. private int age;04. private int buff = 0;//buff判断内容是否已被更新或提取,0为未更新,1为已更新05. int Age06. {07. get08. {09. Monitor.Enter(this);//获取此对象的排他锁10. if (buff == 0)//若内容为空或未更新就使此线程等待11. {12. MessageBox.Show("内容为空或未更新");13. Monitor.Wait(this);//释放锁并等待14. }15. buff--;16. MessageBox.Show("读取内容");17. Monitor.Pulse(this); //通知等待队列的线程,此对象状态要更改18. Monitor.Exit(this);//释放排他锁19. return age;20.21. }22. set23. {24. Monitor.Enter(this);25. if (buff == 1)26. {27. MessageBox.Show("内容还没被读取");28. Monitor.Wait(this);29. }30. buff++;31. MessageBox.Show("写入内容"+value);32. age = value;33. Monitor.Pulse(this);34. Monitor.Exit(this);35. }36. }37. }public class mt{private int age;private int buff = 0;//buff判断内容是否已被更新或提取,0为未更新,1为已更新int Age{get{Monitor.Enter(this);//获取此对象的排他锁if (buff == 0)//若内容为空或未更新就使此线程等待{MessageBox.Show("内容为空或未更新");Monitor.Wait(this);//释放锁并等待}buff--;MessageBox.Show("读取内容");Monitor.Pulse(this); //通知等待队列的线程,此对象状态要更改Monitor.Exit(this);//释放排他锁return age;}set{Monitor.Enter(this);if (buff == 1){MessageBox.Show("内容还没被读取");Monitor.Wait(this);}buff++;MessageBox.Show("写入内容"+value);age = value;Monitor.Pulse(this);Monitor.Exit(this);}}}lock的用法:
[csharp] view plaincopyprint?01.//lock的用法02. int Age203. {04. get05. {06. lock(this) //开始阶段,自获取了排他锁07. {08. if (buff == 0)//若内容为空或未更新就使此线程等待09. {10. MessageBox.Show("内容为空或未更新");11. Monitor.Wait(this);//释放锁并等待12. }13. buff--;14. MessageBox.Show("读取内容");15. Monitor.Pulse(this); //通知等待队列的线程,此对象状态要更改16. return age;17.18. }//结束阶段,释放了排他锁19. }20. set21. {22. lock (this)23. {24. if (buff == 1)25. {26. MessageBox.Show("内容还没被读取");27. Monitor.Wait(this);28. }29. buff++;30. MessageBox.Show("写入内容" + value);31. age = value;32. Monitor.Pulse(this);33. }34. }35.36. }//lock的用法int Age2{get{lock(this) //开始阶段,自获取了排他锁{if (buff == 0)//若内容为空或未更新就使此线程等待{MessageBox.Show("内容为空或未更新");Monitor.Wait(this);//释放锁并等待}buff--;MessageBox.Show("读取内容");Monitor.Pulse(this); //通知等待队列的线程,此对象状态要更改return age;}//结束阶段,释放了排他锁}set{lock (this){if (buff == 1){MessageBox.Show("内容还没被读取");Monitor.Wait(this);}buff++;MessageBox.Show("写入内容" + value);age = value;Monitor.Pulse(this);}}}-----------------------------------------------------------------lock 与 Monitor 的注意事项-----------------------------------------Monitor注意的地方:用Monitor类的Enter方法和Exit方法来管理对象的锁时,要想释放锁,必须显示调用Exit方法。调用Exit方法之前如果某个方法中引发了一个异常,并且这个异常没有被捕捉到,方法就会终止,而且不会调用Exit方法。因此锁没有被释放。为了避免这种错误,可以将可能引发异常的代码放入一个try模块,并将对Exit方法的调用放在相应的finally块上以确保释放锁。使用一个Lock块来管理同步对象上的锁,可以避免忘记调用Monitor类的Exit方法来释放锁。Lock处于某种原因二终止时,C#会隐式调用Monitor类的exit方法。如此一来,即使在代码中出现异常,也可以将锁释放。 
转自:http://software.intel.com/zh-cn/blogs/2012/06/15/400010577/?cid=sw:prccsdn2280
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 游泳的时候泳裙飘起来怎么办 两岁宝宝误服了酵素梅怎么办 人被困在山洞里没有氧气怎么办? 一个人太爱你可你不爱他怎么办 牙齿还没掉又长了新牙齿怎么办 两岁宝宝牙齿发黑烂牙怎么办 怀孕八个月被小孩压到肚子了怎么办 在花场上班客人约我出去玩怎么办 小天才电话手表开不了机怎么办 黑色笔芯弄在白色衣服上怎么办 su文件打开是意外的格式怎么办 su卡的动一下就卡怎么办 犀牛vary渲染的太曝光了怎么办 脑子老是乱想幻想控制不住怎么办 猫抓了破了点皮怎么办 小孩子喜欢玩别人家的玩具怎么办 孩子把别人家的玩具玩坏了怎么办 小新和爸妈一起睡觉那他们怎么办 ps画纸画的时候一直在移动怎么办 宝宝磕碰到家具上鼻梁碰破该怎么办 月经推迟11天了怎么办孕测棒单杠 小孩子不小心把蜡笔吃一点怎么办 线切割切割的工件表面有条纹怎么办 苹果手机不能用流量更新吃鸡怎么办 吃鸡更新成雨林如果内存不够怎么办 绝地求生刺激战场背包满了怎么办 绝地求生刺激战场模拟器满了怎么办 绝地求生刺激战场电脑版满了怎么办 绝地求生手游模拟器注册上限怎么办 绝地求生电脑模拟器已达上限怎么办 三星s5锁屏密码忘了怎么办 字画装框的时候起褶皱怎么办 指甲油抹在手上不在指甲上怎么办 我把油画的布割破了怎么办 胜战本领怎么看、走上战场怎么办 胜战本领怎么看 走上战场怎么办 数码相机拍出的相片亮度太亮怎么办 国考照片错了怎么办招生办能改吗 国考英语准考证名字错了怎么办 玻尿酸打鼻子双眼间距好怪怎么办 喝咖啡后胃不舒服想吐怎么办