1.NET程序设计杨剑yang_jian03@126.com2C#程序设计语言第一章:.NET与C#概述第二章:面向对象程序设计第三章:集合、索引器与泛型第四章:程序调试与异常处理第五章:基于事件驱动的程序设计第六章:Windows程序设计技术第七章:C#数据库编程技术第八章:文件操作与编程技术第九章:多线程和异步编程第九章多线程和异步编程4本章目标掌握线程的同步策略了解进程及线程的概念掌握使用C#进行多线程的创建及简单控制了解线程池技术掌握异步编程的设计与实现技术5同时执行所有任务,时间更少,效率更高人体线程简介读,写一览无遗血液循环在同一时间点执行各项进程•编译程序•发送/接收邮件•打印文件•其他操作系统允许计算机同时执行多项操作程序(进程)6概述程序1程序2程序3这样的运行方式会浪费计算机宝贵的处理能力例如:等待用户输入的时候多任务通俗的来说,就是一个人在同一时间做几件事情所以在这一章节里我们会详细的说到多任务的技术,以及进程和线程的概念,以及如何使用线程,委托等操作我们也要让电脑能在同一时间做多个事情.这样我们就必然引入多任务的思想.7单任务处理执行执行完毕执行任务1任务2任务3任务4CPU多任务处理请求CPU等待返回硬盘读取完成运算等待输入读取设备数据CPU不能同时执行多种操作8执行多任务处理执行任务1任务2任务3任务4CPU上下文切换多任务处理请求充分利用其资源硬盘读取完成运算等待输入读取设备数据9线程简介程序1程序2线程1线程2线程3线程1线程2线程3单独的执行路径10包含一个程序运行单元多任务处理技术应用Windows应用程序界面网络通信服务器程序多任务处理充分利用其资源消息机制应用程序绑定信息不能响应程序界面不受干扰应用程序充分利用CPU处理能力提高并发性11线程简介在以下情况中可能要使用到多线程:程序需要同时执行两个或多个任务程序要等待某事件的发生,例如用户输入、文件操作、网络操作、搜索等后台程序12线程和进程线程的生命周期13System.Threading命名空间System.ObjectSystem.Threading.ThreadStateSystem.DelegateSystem.Threading.ThreadPrioritySystem.MulticastDelegateSystem.Threading.ThreadStartSystem.Threading.ThreadSystem.Threading.ThreadAbortExceptionSystem.ThreadStateExceptionSystem.SystemExceptionSystem.ExceptionSystem.EnumSystem.ValueType14Thread类的属性和方法2-1引用System.Threading命名空间Thread线程实例名=newThread(newThreadStart(方法名));运行在线程上的方法只创建但不启动线程线程实例名.Start();15Thread类的属性和方法2-2属性CurrentThreadIsAliveNamePriorityThreadState方法Sleep()Abort()Join()Resume()Start()Suspend()静态静态16启动线程创建线程对象实例构造函数以ThreadStart委托作为它的惟一参数上例中,MyClass.AStaticMethod方法的代码被执行直到Thread.Start方法被调用,线程才开始执行ThreadStart委托引用新线程将要执行的方法Threadt=newThread(newThreadStart(MyClass.AStaticMethod));t.Start();17示例classSimpleThreadDemo{staticvoidMain(string[]args){Thread.CurrentThread.Name=“主线程;ThreadobjThread=newThread(newThreadStart(ActionMethod));objThread.Name=“子线程;//启动子线程,并为该线程执行ActionMethodobjThread.Start();//这将为主线程执行ActionMethodActionMethod();}staticvoidActionMethod(){for(intcount=1;count=10;count++){Console.WriteLine(“线程名:+Thread.CurrentThread.Name);}}}实例化objThread线程并开始执行ActionMethod()将由应用程序线程执行输出结果混乱18调度线程2-1程序1程序2线程1线程2线程3线程1线程2线程3先执行哪个线程?19调度线程2-2ThreadPriority枚举成员说明AboveNormal安排在优先级为Highest(最高)的线程之后,以及优先级为Normal(普通)的线程之前。BelowNormal安排在优先级为Normal(普通)的线程之后,以及优先级为Lowest(最低)的线程之前。Highest安排在任何其他优先级的线程之前。Lowest安排在任何其他优先级的线程之后。Normal安排在优先级为AboveNormal的线程之后,以及在优先级为BelowNormal的线程之前。默认情况下,线程的优先级为Normal(普通)。20示例staticvoidTaskTwo(){for(intindex=5000;index=4990;index--){Console.WriteLine(index);}}staticvoidMain(string[]args){ThreadobjThreadOne=newThread(newThreadStart(TaskOne));ThreadobjThreadTwo=newThread(newThreadStart(TaskTwo));objThreadOne.Start();objThreadTwo.Start();}staticvoidTaskOne(){for(intcount=1;count=5;count++){Console.WriteLine(count*2);}}无优先级线程,同时执行,输出无序….21示例staticvoidMain(string[]args){Thread.CurrentThread.Name=“主线程;ThreadobjThreadOne=newThread(newThreadStart(TaskOne));objThreadOne.Name=“子线程1;ThreadobjThreadTwo=newThread(newThreadStart(TaskTwo));objThreadTwo.Name=“子线程2;//这将启动子线程objThreadOne.Start();objThreadTwo.Start();objThreadTwo.Priority=ThreadPriority.Highest;}将在执行第一个线程前执行objThreadTwo22利用线程提供方法管理线程管理线程Thread.Sleep(3000);//阻塞3秒Thread.Sleep引起当前线程阻塞Suspend和Resume方法通常没用处会导致像死锁这样严重的应用程序问题t.Start();t.Join();//等待t线程退出Thread.Join等待其他线程退出希望t执行后继续操作主线程等待子线程结束后Join()方法返回23中断和终止线程Thread.Interrupt方法任何等待状态唤醒线程并引发ThreadInterruptedException异常运行等待睡眠唤醒24线程安全概述线程之间共享数据和资源的普遍问题死锁线程之间互相等待从而阻止线程继续执行争用条件未受控制的代码执行顺序会引起错误最好的办法是尽可能避免共享数据把数据封装在不被共享的对象中.NETFramework提供了三种策略来同步对实例方法、静态方法和实例字段的访问手动同步同步代码区域同步上下文线程不协作效用打折扣保证安全性避免争用避免逻辑混乱避免死锁避免同时修改25同步上下文[Synchronization()]classCounterSynchronizedContext:ContextBoundObject{staticintsCount=0;//可被多个线程同时访问intiCount=0;//一次只有一个线程可访问publicvoidIncrement(){//…同一事件只有一个线程可访问}}使用SynchronizationAttribute属性为ContextBoundObject类型对象提供简单、自动的线程同步只有成员字段和成员方法被同步静态方法和字段不被保护,允许多个线程同时访问26同步上下文好处从特定类继承,再加属性额外代码限制成员方法和成员字段安全从ContextBoundObject类继承不能保护静态变量较高层次保护只被一个线程访问效率低更细级别灵活性低27同步代码区域Monitor用途:告诉系统从哪条语句进入同步区域退出同步区域Monitor.Enter开头使用结尾使用保护整个方法Monitor.Exit28同步代码区域Lock和SyncLock可以用lock(this)来保护lock方法所在的类,保证类中实例方法的同步用SyncLockGetType(class)来保护静态成员(lock内部使用Monitor类)lock(typeof(Counter)){//被保护的代码}关键字支持本质使用Monitor类实现保护实例成员和方法保护静态方法和成员保护实例类型,则应写成lock(this)或SyncLock(me)29手动同步ReaderWriterLock类——支持单个写进程多个读进程手动进入,退出同步区域类支持单写多读线程1线程2线程3线程4读取修改线程数据写线程优先级高线程5线程6线程7线程830手动同步usingSystem;usingSystem.Threading;classResource{ReaderWriterLockrwl=newReaderWriterLock();publicvoidRead(Int32threadNum){rwl.AcquireReaderLock(Timeout.Infinite);try{//许多线程可以进行读操作处理,写线程被阻塞……}finally{rwl.ReleaseReaderLock();}}31手动同步publicvoidWrite(Int32threadNum){rwl.AcquireWriterLock(Timeout.Infinite);try{//一个线程可以进行写操作处理,读线程被阻塞……}finally{rwl.ReleaseWriterLock();}}}32线程池进程线程线程线程线程线程池线程池用来提高应用程序效率基于计算机的所有进程进行优化ThreadPool类QueueUserWorkItem方法自动分配任务给空闲线程线下列情况下不要使用线程池任务需要一个特别的优先级有些任务可能需要运行很长时间需要把线程放到一个单线程的单元中需要通过一个稳定的标识和线程关联33usingSystem;usingSystem.Threading;publicclassExample{publicstaticvoidMain(){//将任务加入线程池的任务队列ThreadPool.QueueUserWorkItem(newWaitCallback(ThreadProc));Console.WriteLine(Mainthreaddoessomework,thensleeps.);//主线程等待Thread.Sleep(1000);Console.WriteLine(Mainthreadexits.);}//线程函数staticvoi