《NET4 技术亮点剖析-金老师.ppt》由会员分享,可在线阅读,更多相关《NET4 技术亮点剖析-金老师.ppt(70页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、北京理工大学计算机学院 金旭亮.NET 4.0 技术亮点剖析.NET技术王国探秘并行计算的时代“拥抱变化”的软件系统“动静结合”的编程世界主要内容21.NET技术王国探秘不断进取的.NET4两个重要的里程碑What is.NET?.NET Framework=CLR+基类库ildasmReflector探索.NET技术的两把锋利的手术刀5Reflector:用过的人都说好可以反汇编程序集的Reflector6然而,仅有技术是不够的7IL(Intermediate Language),CLR能识别的“面向对象”的汇编语言。What is IL?8使用ildasm工具IL指令程序集元数据9var
2、v=new Amount=108,Message=Hello;ildasm小试牛刀ildasm揭穿了编译器玩的小把戏,“匿名类型”其实是一块“语法糖(syntactic sugar)”。10对于应用层的开发,大多数情况下,即使不了解IL也没有多大影响。对于有以下需求的开发者而言,掌握IL还是很有必要的:.NET开发者是否需要掌握IL?希望深入探索CLR的内部机理更好地理解语言编译器的特性从底层开始优化程序性能将其他的编程语言移植到.NET平台上开发一些“底层的”开发工具(比如Reflector)11并行计算的时代CPU的多核化,驱动着软件开发进入并行计算的时代。并行计算与多核CPU装备了 4
3、核 8 线程CPU的台式计算机13要完成之数据处理任务:递增一个整数数组中的每个元素值,完成整个数据处理工作需108次操作。并行计算程序引例:SequentialvsParallel 顺序执行,453毫秒分解为4个任务并行执行,235毫秒为每个数据项的每个操作建立一个并行任务,3810毫秒14并行计算所带来的挑战示例非常清晰地展示出并行程序设计的特殊性,并非“并行”总比“串行”快,到底怎样才能获得最大的加速,需要仔细地设计并行算法,并且应该在多个典型的软硬件环境中进行对比测试,最终才能得到理想的并行设计方案。开发并行程序的关键在于要找到一个合适的任务分解方案。并行总要付出一定的代价,比如线程同
4、步、线程通讯、同步缓冲数据等都是开发并行程序必须认真考虑的问题。15并行程序与串行程序的对比项目目串行程序串行程序并行程序并行程序程序行为特性可以预期的,相同运行环境下总可以得到相同的结果如果没有提供特定的同步手段,则程序执行的结果无法预期内存访问独占访问内存单元,数据可靠有可能因多线程同时存取同一内存单元而引发数据存取错误锁不需要必须为共享资源加锁死锁不可能出现可能出现,需要仔细考虑程序中可能出现的种种情况予以避免测试使用代码覆盖的测试方法可以检测出绝大多数BUG由于多个线程同时并行,仅使用代码覆盖的测试方法无法检测出程序中隐藏的BUG,并行程序的测试变得很复杂调试相对简单,可以随时停止程序
5、运行,单步跟踪定位到每条语句和每个变量的值由于多个线程同时运行,当暂停一个线程进行调试时,其他线程可能还在运行中,因此难于保证调试环境的一致性,并行程序的调试非常困难。16.NET 4.0中的并行计算组件17某台计算机安装有多个网络接口(Network Interface),每个网络接口都可以定义自己的网关(Gateway)和DNS服务器,我们希望能以并行的方式检测此台计算机是否联网。TPL应用实例对于所有“已连接”的网卡,应该按以下尝试完成Ping的操作,才能知道是否本机可以访问互联网:1.Ping网关2.Ping DNS服务器3.Ping一个“Well-known”互联网网址(可选)只要有
6、一个网卡Ping操作成功,则认为本机可访问互联网18如果直接采用多线程开发,则必须要精心考虑应该创建多少个线程,并需要实现复杂的线程同步:用经典多线程技术实现太麻烦了!191.一个线程在合适的时候需要启动另一个线程2.一个线程需要通知另一个线程取消工作3.多个线程不能同时写入共享变量4.TPL提供了一个“Parallel”类,可以使用它的ForEach方法来并行处理数据集合中单个数据项可以并行执行的循环20foreach(var item in sourceCollection)Process(item);Parallel.ForEach(sourceCollection,item=Proce
7、ss(item);串行执行并行执行TPL为并行循环内置了“中途取消”的机制并行循环的提前中止21示例中使用Parallel.ForEach启动对所有网卡的并行检测,并且在已经有一个网卡Ping通互联网的情况下“通知”其他正在执行的并行循环退出并行执行的“联网”检测示例程序示例程序:示例程序:IsOnLine22TPL提升了开发“并行计算”的抽象层次,基于“任务(Task)”而非“线程(Thread)”来开发并行计算程序。“任务(Task)”可以看成是一个可以并行执行的某项工作TPL使用.NET线程池中的线程来执行任务。负责将任务“分派”到线程的工作由任务调度器负责,而任务调度器集成于线程池中。
8、任务并行库(TPL,Task Parallel Library)23任务的创建直接使用构造函数:Task t=new Task()=任务方法代码);t.Start();使用任务工厂Task t=Task.Factory.StartNew()=任务方法代码 );24TPL提供了许多任务同步手段Task task1=new Task()=DoStep1(););Task task2=task1.ContinueWith(PrevTask)=DoStep2(););task1.Start();25让一个任务结束自动启动另一个任务更多的同步手段Wait:等待单个任务的完成。WaitAll:等待一组任务
9、的全部完成。WaitAny:等待一组任务的任何一个任务完成。Task t=Task.Create(.);t.Start();.t.Wait();Task t1=Task.Create(.);Task t2=Task.Create(.);Task t3=Task.Create(.);/启动3个任务的执行.Task.WaitAll(t1,t2,t3);26“父子类型”的任务Task tskParent=new Task()=/父任务完成的工作父任务完成的工作 /创建后继子任务并自动启动创建后继子任务并自动启动 Task.Factory.StartNew()=MethodA();Task.Facto
10、ry.StartNew()=MethodB(););/启动父任务启动父任务tskParent.Start();/等待整个任务的完成等待整个任务的完成tskParent.Wait();27任务对象的状态机28并行循环也需要被转换为Task29并行任务由线程池中的线程负责执行30Program Thread任务窃取.NET 4.0 线程池的新变化Lock-FreeGlobal QueueLocalWork-Stealing QueueLocal Work-Stealing QueueWorker Thread 1Worker Thread pTask 1Task 2Task 3Task 5Task
11、 4Task 631Parallel LINQ.NET 4.0 引入的PLINQ是LINQ的“升级换代”技术,PLINQ实现了对“内存”中的数据进行并行查询。LINQ转换为PLINQ非常简单:var source=Enumerable.Range(1,100);var evenNums=from num in source.AsParallel()where num%2=0 select num;32PLINQ的性能提升设计者在设计PLINQ,追求的一个目标是:PLINQ绝不能比它的前辈-LINQ to Object运行得更慢!如果在某个地方做不到,它就采用串行方式执行。示例项目WhoIsFa
12、ster:从10万个整数中选出质数33顺序执行 vs 并行执行示例程序 MyImageProcessor34示例程序在不同硬件平台上的性能比对结果处理时间(毫秒)Mobile Pentium 42.4GCore2 T55001.6GCore i5 M4602.53GCore i7 8702.93G0500100015002000250030003500400045005000不同CPU的性能对比单线程版TPL版35有关并行计算的开发建议数据处理工作比较简单时,通常串行算法更优。数据量非常大,或者单个数据项的处理工作比较复杂,使用并行算法。推荐按照以下从易到难的顺序来编写并行代码:1.基于PLI
13、NQ的声明式编程方式2.使用Parallel类的“简单并行”编程方式3.使用Task的直接基于TPL的“任务并行”编程方式4.使用线程的直接基于CLR的传统“多线程”编程方式。36“拥抱变化”的软件系统世界总是在不断地变化中,而软件系统则相对稳定,并且通常需要高昂的开发费用与维护成本。如何尽可能地延长现有软件系统的生命,是一个很有意义的问题。“与时俱进”的软件系统,能够不断以“小”的调整来积极地应对外部的变化,人们迫切地希望能更方便快捷地设计和开发出这样的软件系统。技术背景38软件的可扩展性所谓“可扩展性(extensibility)”主要是指为一个现有的软件系统扩充功能到底需要付出多少代价。
14、我们通常通过一组精心设计的软件构造块,以类似于搭积木的方式构造系统。可扩展性强的软件系统,只需提供更多的新构造块,或者以另一种方式组合现有构造块,就可以方便地修改它的功能集合。软件系统构造块应该具有很强的组合能力,小的构造块可以聚合为大的构造块,而这些大的构造块又是更大的构造块的有机组成部分。39开放/封闭原则(Open/Closed Principle)40SoftwareentitiesshouldbeopenforSoftwareentitiesshouldbeopenforextension,butclosedformodification.extension,butclosedfor
15、modification.软件实体应该对扩展开放,而对修改封闭。为软件系统设计一个相对稳定的框架,而将需要变化和扩充的部分独立为“插件(Plug-in)”,是实现软件系统高可扩展性的一种重要技术。基于早期版本(3.5及以前)的.NET,通常使用“反射(Reflection)”技术来设计插件系统,其问题在于:“插件”技术插件的接口设计、插件的发现和装载,往往都是手工完成的,仅适用于特定程序,不具有通用性。插件系统的开发是低效的。41早期插件技术的示例示例ComponentPlugInDemo示例的系统架构42由于开发基于插件的软件系统的需求日益迫切,.NET 3.5 引入了一个“托管插件框架(M
16、anaged Add-ins Framework,MAF)”.MAF集成了自动识别与装载插件、处理异常、动态卸载插件等功能,是一个完备的插件开发平台。然而,MAF拥有一个非常复杂的基于“管道(pipe line)”的架构,即使是创建一个最简单的插件和宿主示例,也得创建最少8个项目!过于复杂的东西没人愿意用!MAF:并不算成功的“尝试”43.NET 4.0基类库多了一个“MEF(Managed Extensibility Framework,托管可扩展性框架)”。MEF将一个.NET应用程序看成是普通软件组件与另一种可组合“部件(Part)”所构成的整体,并且部件的组合发生在程序运行时,这实际上
17、就是把.NET应用程序由“静态编译”转换为“动态组合”,将.NET平台的代码复用技术提升到了一个新的水平。MEF一出,谁与争锋?44定义部件协定What is MEF?(1)public interface IPlugIn void Print(string message);Export(typeof(IPlugIn)public class MyPlugIn:IPlugIn public void Print(string message)/实现部件协定45What is MEF?(2)public class MyHost Import(typeof(IPlugIn)public IPl
18、ugIn plugin=null;public void Run()public void Run()var container=new CompositionContainer();container.ComposeParts(this,new MyPlugIn();if(plugin!=null)plugin.Print(“Hello!”);动态装配部件宿主定义部件宿主46MEF应用程序的基本构造块部件“部件(Part)”是ComposablePart类的实例。在程序运行时,MEF使用反射技术抽取附加于特定类型之上的“Import”和“Export”标记信息,用于创建ComposableP
19、art对象。“导入(Import)”描述了一个部件需要外界的哪种服务。“导出(Export)”描述了一个部件能向外界提供什么服务。47部件的装配车间部件组合容器MEF应用程序在运行时,通常会将部件宿主对象(即附加有 Import标记的对象)装入到部件组合容器中。部件组合容器会检查部件宿主对象所定义的“导入(Import)”信息,在其本容器范围内查找匹配的定义有对应的“导出(Export)”的部件对象,将其“组合”到宿主对象中。48协定名是部件间相互匹配的依据,只有协定名一致的部件才被认定为是“匹配的”,它们之间的组合才能进行。部件间的“通讯录”Catalog.NET 4.0提供了四种类型的部件
20、编目“部件编目(catalog)”的作用的作用类似于电话号码本类似于电话号码本,它,它保存了部件的相关信息保存了部件的相关信息491.TypeCatalog(类型编目)(类型编目)2.AssemblyCatalog(程序集编目)(程序集编目)3.DirectoryCatalog(文件夹编目)(文件夹编目)4.AggregatingCatalog(复合编目)(复合编目)通用的MEF组合部件的步骤1.为每个需要组合部件的类型定义为每个需要组合部件的类型定义“导入(导入(Import)”,为每个将要被组合的部件类型定义为每个将要被组合的部件类型定义“导出(导出(Export)”。2.创建一个创建一个
21、“编目(编目(Catalog)”对象,对象,MEF将使用它来查将使用它来查找匹配的部件。找匹配的部件。3.创建一个部件容器对象,关联上前面创建的编目对象。创建一个部件容器对象,关联上前面创建的编目对象。4.将部件宿主对象的引用传给部件容器对象将部件宿主对象的引用传给部件容器对象5.调用部件调用部件组合组合容器对象的容器对象的ComposeParts扩展方法组合部扩展方法组合部件。件。50MEF的应用实例 示例项目NonCompileSystemUpdateUseMEF51可分块下载的Silverlight 4应用程序Silverlight 4所提供的DeploymentCatalog派生自Co
22、mposablePartCatalog,它可以识别出一个xap包中的部件,并且支持“基于事件的异步调用模式(EAP)”,提供了异步下载xap包的功能。示例解决方案DownLoadOnDemandUseMEF52示例分析分块后的Silverlight应用程序包之间的依赖关系53Silverlight 4+MEF+MVVMModel代表应用程序要处理的数据对象,View代表用于显示数据的可视化界面,而ViewModel则解决“如何将Model以特定的方式显示在View上”这个任务。这一模式的核心思想是将处理应用程序界面显示逻辑的代码独立地放置到ViewModel类中。示例解决方案DownLoadO
23、nDemandUseMEF2。54“动静结合”的编程世界C#的历史回顾56可以动态添加成员的对象:神奇的dynamic(1)dynamic dynamicObj=new ExpandoObject();/动态地添加成员(字段或方法)dynamicObj.Value=100;dynamicObj.Increment=new Action()=dynamicObj.Value+);/动态地移除方法dic=dynamicObj as IDictionary);dic.Remove(Increment);57简化与COM组件交互的代码神奇的dynamic(2)Word.Document doc=wor
24、dapp.Documents.Open(ref fileName,ref argu,ref argu,ref argu,ref argu,ref argu,ref argu,ref argu,ref argu,ref argu,ref argu,ref argu,ref argu,ref argu,ref argu,ref argu);dynamic wordapp=new Word.Application();dynamic doc=wordapp.Documents.Open(FileName:“MyDoc.docx”);58让类型派生自DynamicObject,并重写相应的方法,即可创
25、建自己的动态类型。创建自己的动态类型dynamic obj=new MyDynamicType();/动态添加字段obj.Name=C#;/动态添加方法Action act=(self)=Console.WriteLine(self.Name);obj.DynamicMethod=act;示例解决方案CSDynamicExample59将保存有MyDynamicType的程序集放到指定文件夹(比如d:test),然后启动IronPython动态语言使用C#开发的动态类型IronPython测试命令清单60背后的“主角”DLR61DLR探秘(1)自动创建的新类型dynamic d=100;d+;
26、private static class o_SiteContainer0 public static CallSiteFunc p_Site1;动态站点:CallSiteC#写的动态调用语句C#编译器62动态站点对象通过CallSite.Create方法创建,C#编译器会为其指定一个派生自CallSiteBinder的对象(称为“动态站点绑定对象”)作为其参数。动态站点绑定对象的主要工作是将代码中的动态表达式(本例中为d+)转换为一棵“抽象语法树(Abstract Syntax Tree,AST)”,这棵语法树被称为“DLR Tree”,扩充自.NET 3.5引入的LINQ表达式树。将动态表
27、达式转换为DLR表达式树的过程,称为“绑定(Bind)”,完成这一工作的对象就是“动态站点绑定对象(CallSiteBinder)”。DLR探秘(2)动态站点对象与绑定63DLR探秘(3)动态表达式的最终形式object d=100;object CS$0$0000=d;/创建动态调用站点对象if(p_Site1=null)p_Site1=CallSiteFunc.Create();/完成动态调用d=p_Site1.Target(p_Site1,CS$0$0000);dynamic d=100;d+;C#编译器64示例项目:IsDynamicSlowly动态代码的性能问题DLR拥有一个3级的缓
28、存架构,最多可缓存100个动态调用的解析结果(这些解析结果被称为“规则(Rule)”)。仅仅是第一次调用时比较慢,后继的调用其性能可以逼近静态代码!65静态和动态编程语言的完美配合PythonBinderRubyBinderCOMBinderJavaScriptBinderObjectBinderDynamic Language RuntimeExpression TreesExpression TreesDynamic DispatchDynamic DispatchCall Site CachingCall Site CachingIronPythonIronRubyC#VB.NETOthers66在DLR的支持之下,可以让静态编程语言使用动态语言所开发的库,反过来,基于DLR实现的动态编程语言也能使用为.NET静态编程语言所设计的库。我们的结论67Anders Hejlsberg说:whats new in C#5.0?68未来的编程语言应该是多范式的,具有高度的可组合性,在一个项目或产品中组合多个编程语言、使用多种编程范式会变得越来越普遍。未来之路69北京理工大学计算机学院北京理工大学计算机学院 金旭亮金旭亮电子邮件:电子邮件:JinXuL技术博客:技术博客:1.CSDN:http:/ Question?70谢谢谢谢大家!大家!