您的当前位置:首页正文

使用C#中线程同步、事件及异步委托机制实现定单模式

来源:九壹网
维普资讯 http://www.cqvip.com

第23卷第7期 计算机应用与软件 Vo1.23,No.7 2006年7月 Computer Applications and Software Ju1.2006 使用C#中线程同步、事件及异步委托机制实现定单模式 余建华 蔡瑞英 方寿海 (南京工业大学信息科学与工程学院江苏南京210009) 摘要 c}}语言中的委托、事件及异步委托是通用类型系统所特有的语言特性,它功能强大,使用方便。本文结合c}}源代码,介 绍了利用这些特性所实现的定单模式和传统的多线程同步机制实现定单模式的不同。 关键词 多线程同步机制 事件 委托 异步委托 定单模式 ACCoMPLISHING THE SUBSCRII rIoN PATTERN BY USING THE MECHANISMS oF THREAD SYNCHRoNIZATIoN, EVENT DELEGATE AND ASYNCHRoNoUS DELEGATE IN C荐 Yu Jianhua Cai Ruiying Fang Shouhai (College ofInformation Science and Engineering,Nanjing University ofTechnology,Nanjing Jiangsu 210009,China) Abstract Delegate,events and asynchronous delegate which is the special peculiarities in common type system are power and convenient. With C}}source code.this article introduces how to accomplish the subscription pattern by using these peculiarities and compares the differ・ ences between them. Keywords Thread synchronization Event Delegate Asynchronization delegate Subscription pattern tResuh类的对象(第四线程在此对象中运行。)用以取得前三线 0 引 言 程的结果进行后续操作。 (1)GetResuh类是取得前三个线程的运算结果,并进行后 使用多线程技术编程有两种主要方式:其一,子线程独立完 续操作的类。 成某一逻辑功能,主线程在启动它后不再过问;其二,主线程在 成员变量ok数组用以标识前三个线程的运行结果现在是 启动子线程后,需要用子线程的处理结果(通常是多个子线程 否可以使用。 的处理结果)进行后续操作。这后一种方式又称为定单模式。 sum,subtration,multiplication以GetResuh类对象成员变量 其本质是实现多线程间前趋与后继次序关系的模式。 的方式被关联到AddAsync和MuhiAsync类的对象里用以存储 本文将结合具体代码介绍在c}}中,利用三种不同机制实现 这三个线程的运算结果。 定单模式。首先是使用c}}中的多线程同步机制,然后再应用通 public void Result() 用类型系统所特有的委托,事件及异步委托功能分别实现定单 {Thread tempGetResuh Thread=new Thread(new ThreadStart(Ge・ 模式。并对这三种实现机制的特点加以讨论。 tResuhThread)); tempGetResuhThread.Start(): 1 利用C撑中的多线程同步机制实现定单模式 private void GetResuhThread() 现在我们需要求解这样一个问题。给定两组数,先求出第 {lock(this) 一组的和、差,以及第二组数之积;再把得到的三个结果求积。 while(!ok[0]ll!ok[1 1 0k[2])Monitor.Wait(this) 我们假设这里的求和、求差和求积都是比较耗时的操作 为了 } 提高程序执行效率,或者提高主线程的响应度,我们将分别用三 DoSomeOtherWork(); 个线程(前趋线程)做第一步操作,第四个线程(后继线程)做第 二步。第四个线程需要用到前三个线程的运行结果,因而可以 私有函数void GetResuhThread()用以生成线程委托,实际 使用定单模式来协调这四个线程的关系。主线程用来启动各个 上是第四个线程的执行角本。我们可以清晰地看到这个函数只 线程。 干了两件事:判断前三个线程是否出了结果,是,就是它们作后 这里AddAsync类的对象(第一,第二线程在此对象中运 行。)用以存储、计算第一组数的和、差。MuhiAsync类的对象 收稿日期:2005-07—20。余建华,硕士生,主研领域:计算机网络 (第三线程在此对象中运行。)用以计算第二组数的积。Ge. 通信与安全 维普资讯 http://www.cqvip.com

第7期 余建华等:使用c#中线程同步、事件及异步委托机制实现定单模式 143 续处理;还没有,就令此线程睡眠等待结果出来。这里之所以在 访问逻辑标志时加上GetResuh类对象的锁,是因为此逻辑标志 将要在AddAsync和MuhiAsyne类对象,也就是前三个线程里被 修改,因此需要互斥。此外,线程同步机制wait,pulse要求在对 象锁里使用。公共接口函数Void Result()被主线程调用用以启 动第四个线程。 (2)AddAsync类用以生成两个线程,计算第一组数的和、 差的类。 internal AddAsync(GetResult getResult,int numl,int num2) {this.getResult getResuh; this.numl:numl: this.num2:num2: numl,num2两个实例变量用以存储第一组数。我们在Ad— dAsync类的构造函数中把这两个数存进来。同时存进来的有 AddAsync类所关联的GetResuh类对象,我们正是通过这个对 象把计算好的和差回传。 Dub1ic void WorkStart() {Thread addThraed:new Thread( new Th adStart(AddThread)): addThread.Start() Thread subThread:new Thread( new ThreadStart(SubThread)): SUbThread.Start(): private void AddThread() {fnr(int i:0;i<90000000;i++); getResuh.sum numl+num2: lock(getResuh) {getResuh.ok[O]:true; Monitor.PulseAll(getResult); AddThread()是用以生成第一,也就是求第一组数和线程的 委托对象函数(即第一线程的执行角本)。我们看到这两个函 数在算出结果后即刻把关联进来的getResult对象加锁,用以把 计算结果回传给此对象的sum域,并唤醒第四个线程,告诉它 sum值已经可用,让其检查其它线程是否也已经准备好,以便进 行后续操作。For循环增加AddThread线程处理时间,延缓第一 组数相加结果的出现,以检测作为前趋的三个线程与第四线程 的交接机制。SubThread函数及MuhiAsync类的MuhiThread函 数与AddThread类似,只不过执行的是第一组数求和及第二组 数求积的操作,这里不再复述。 (3)在主函数中的调用 GetResuh getResuh:new GetResuh(); AddAsync addAsync=new AddAsync(getResuh,100,200); MultiAsync multiAsync:new MuhiAsync(getResult,100,200); addAsync.WorkStart();muhiAsync.WorkStart();getResult.Result(); (4)利用多线程的同步机制实现定单模式在Java中就有 实现(参考文献[1])。本文使用c#的线程同步机制来实现定 单模式的思想即来源于此,但作了两个关键的改进。其一:原书 中把获取结果和执行前趋任务的函数放在一个类中定义,这样 固然可以简化编程,但由于在实际应用中,前趋任务往往有多 个,且种类不同,因此需要用多个类来刻画描述这些任务,所以 有必要把结果获取类和前趋任务类分开定义,这样可以灵活组 合前趋任务执行,轻易实现各种应用逻辑。其二:把获取结果类 的执行函数也变成一个与前趋任务线程同等地位的独立线程来 执行,而不是在主线程中执行。这样可以不影响主线程的响应 度,充分利用多线程的优点。 2使用通用类型系统特有的委托事件机制实 现定单模式 —— —————————. j 毒挪动毫美t (1)在委托事件机制中,首先谈一下事件参数类AddEven— tArgs。事件参数类的作用在于暂存前趋任务线程的计算结果, 并通过事件激发机制传递给后继线程。很显然它就相当于前趋 线程发给后继线程的一封信,而送信人是委托事件对象event ResuhEventHandler result。 (2)GetResuh(后继任务)对象不再关联进AddAsync,Mul— tiAsyne(前趋任务)对象中,取而代之的是委托事件对象,由它 来作为前趋后继线程的联系人。并且在前趋线程的执行角本中 把计算好的结果和当前操作类型打包进事件参数对象,激发事 件,引发后继线程处理。 int sum numl+hum2: AddEventArgs addEventArgs=new AddEventArgs(Operation.Add, sum); if(resultl=nul1)restllt(this,addEventArgs): (3)在GetResuh类后继任务事件处理的线程中,根据事件 参数把前趋任务计算的值GetResult类的相应域内,再去检测其 它前趋线程是否完成,以便进行后续操作。 switch(e.operation) {case Operation.Add: ok[0]=true; sum=e.result: break; CaSP…… if(ok[O]&&ok[1]&&ok[2])DoSomeOtherWork(); (4)主线程中的调用 GetResuh getResult:new GetResuh(): -It AddAsync addAsync:new AddAsync(100,200); MultiAsync muhiAsync=new MultiAsync(30,40); addAsync.result+:flew ResullEventHandlerf getResult EventHandler);① muhiAsync.result+=new ResullEventHandlerf getResult EventHandler);② addAsync.WorkStart();mulhiAsync.WorkStart(); 这里特别关注一下①、②步的操作。正是它们把前趋线程 的事件委托对象和后继线程的事件处理函数联系了起来。这 维普资讯 http://www.cqvip.com

l44 计算机应用与软件 nul1);//异步调用。 2006丘 种事件委托对象和事件处理函数的关联机制可以任意组合前趋 线程与后继线程事件处理函数,从而可以轻易实现任何项目中 要求的线程的逻辑关系。 4对多线程同步、事件委托和异步委托机制分 别实现定单模式各自特点的探讨 3 C#中的异步委托机制实现定单模式 多线程同步机制和事件委托机制分别实现定单模式的 在C#中有一种神奇的机制一异步委托。一般意义上的 本质区别在于前趋线程和后继线程如何交接。线程同步机 制事实上是一种询问机制,GetResuh(结果查询)后继线程与 前趋线程同时在处理器中运行。而事件委托机制则是在前 委托是一个函数指针对象。当调用这个委托时,实际上是在 当前线程中执行这个指针对象所指向的函数。而异步委托 则由系统再自生出一个线程来执行这个函数指针对象,并且 可以把委托函数的执行结果通过指定的回调函数取出来,由 程序员自由使用。现在让我们看看由这种机制实现的定单 模式。 (1)在前趋线程的角本中 internal static bool AddThread(int numl,int num2,out int sum) {for(int i:0,i<9OOOOOOO;i++); sum:numl+hum2: return true; 由于系统自动生成线程执行函数,我们在前趋线程脚本 (AddAsync类的AddThread,SubThread函数和MutiAsync类的 MuhiThread函数)编写过程中没有使用生成线程委托,启动线 程这种显示的多线程程序编写方式。完全是在把这些多线程函 数当做普通函数来写。因而与前面两种实现方式完全不同的是 在主函数中,将不再生成前趋线程类的对象,而是通过使用直接 以两组数作为参数的类的静态函数。 (2)异步委托的回调函数 从本质上讲异步委托的回调函数实际上是异步回调委托的 一个对象。这个异步回调委托是一个由系统定义的无返回值, 以一个IAsyncResuh(异步结果接口)为参数的函数原型。我们 在对前三个线程的结果进行后续处理的函数中使用它。 internal void AddResuhs(1AsyncResuh ar) {int sum:0; AddAsyncDele addAsyncDeleg (AddAsyncDele)((Asyn— cResult)ar).AsyncDelegate; if(addAsyncDele.Endlnvoke(out sum,ar)) {this.sum:sum; this.ok[0]:true; if(ok[1]&&ok[2])DoSomeOtherWork(); 在这个后继处理函数中通过IAsyncResuh(异步结果接口) 得到调用这个回调委托对象的异步委托,再从此异步委托中取 出前趋线程的执行结果加以使用。 (3)主函数中的调用 AddAsyncDelegate addAsyncDelegate: . new AddA。yncDelegate(AddAsynchronization.AddThread); //生成一个普通的委托,前趋线程将使用此委托。 GetResuhAndDoSomeWork getResuhAndDoSomeWork: new GetResuhAndDoSomeWork(); //生成一个结果处理类的对象。 AsyncCallback addCallback=new AsyncCallback( getResuhAndDoSomeWork.AddResuhs): //生成前趋线程回调委托的对象。 addAsyncDelegate.Beginlnvoke(numl,num2,out temp,addCallback. 趋线程在结果计算出来后通过激发事件把它传递给后继线 程并引发其运行。这是通知机制,前趋线程与后继线程相继 运行。也就是用查询方式和中断方式来处理10操作的 区别。 异步委托机制处理前趋线程和后继线程交接的方式与事件 委托类似,本质上都是通知机制。但与事件委托不同的是由系 统自己生成线程执行前趋线程的角本,因而虽然是编写多线程 程序,却完全可以按照普通单线程函数编写。程序本身可以简 化,程序员的驰聘空间更大,更自由。 参考文献 [1]结城浩著,Java多线程设计模式,中国铁道出版社,2005. [2]Inside c#,Tom Archer&Andrew Whitechapel Microsotf Press,2003. (上接第128页) (6)会话结束,释放密钥。 从图3可以看出,改进后的WAP协议可以确保点到点的数 据安全。在移动设备和WebServer端都增加了一次加密和解密 的过程。但在一次会话过程中,两者的工作量是不一样的。由 于一般情况下,会话的主动者都是移动设备,所以移动设备还担 负着生成素数和其原根的任务 。 4 总结 面对众多的开发技术与工具。在系统应用的安全性方面, 如何保证私有信息或单位内部信息不受到危害或恶意篡改,如 何防止恶意用户的蛮力攻击等,是目前基于无线网络的移动办 公业务安全性研究的目标与核心。因此,我们将对称加密体制 应用到了整个移动商务的通信模式中,保证了基于WAP协议的 点对点通信的进一步安全性。当然这也带来了计算量增大的问 题,为此可以采用借助第三方进行协同计算的方法来解决,目前 我们正在研究该问题。 参考文献 [1]刘文杰,WAP安全机制研究[J],China Data Communications,2002, No.8:24~25. [2]张曜等,加密解密与网络安全技术[M],北京:冶金工业出版社, 2002.53—58. [3]聂哲,“基于WAP技术的移动商务系统的设计与实现[J]”,《计算 机应用》,2003,Vo1.23:32~34. [4]A.Aziz,T.Markson.Simple Key—Management For Intearct Protocols[J] Interact draft work in progress,1995,December:35—38. [5]Willian Stalling,Cryptography and Network Security[M]Principles and Practice,Peking:Publishing House of Electronics Industyr,2003,156 ~l60. 

因篇幅问题不能全部显示,请点此查看更多更全内容

Top