⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 208004.htm

📁 探索Windows 2000发展策略以及中介层技术设计的基本概念
💻 HTM
📖 第 1 页 / 共 3 页
字号:
<html><body><span  id=Layer1><a name=208004><font color=#3e70d7 face=arial size=5><b>物件生命周期服务</span><span  id=Layer2></b></font><p><font size=2 color=#3c3c3c face=arial>假设,如同大部份的银行一样,QwickBank允许它的顾客检查支票帐户的馀额、转帐、透过电话完成他们的某些要求。为了支援这些服务,QwickBank可能运作一个电话中心,然後让一群员工坐在电脑面前,花费时间来接听电话,代表银行的顾客处理一些事情。让我们假设这些员工使用的软体是建立在Windows 2000 平台之上的叁层式应用程式,透过Visual Basic开发的客户端使用DCOM与位居中间层具交易性的COM物件进行沟通,这些物件再存取一对资料库。图8-16为这个应用程式的简单图示。</span><span  id=Layer3></font></p><p><font size=2 color=#3c3c3c face=arial>就图所阐述,每个客户端都拥有自己的物件。通常交易性物件都是用在这类的应用程式之中,一般来说客户端并不需要共享物件。而客户端直接存取的每个物件可能都是从同一个类别产生的。这代表若一个交易同时有500个客户端,那麽潜在便有500个物件同时存在,每个物件服务一个单独的客户端。</span><span  id=Layer4></font></p><p><font size=2 color=#3c3c3c face=arial>一般来说COM+应用程式的客户端不会共享物件</span><span  id=Layer5></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>一般来说COM+应用程式的客户端不会共享物件</span><span  id=Layer6></font></p><hr><br><center><a target=_new href=imagesh/8-16.gif><img border=0 src='imagesl/8-16.gif'></a></center></span><span  id=Layer7><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b>&nbsp;图8-16</span><span  id=Layer8>&nbsp;</b></font>每个客户端不会共享执在COM+应用程式中的物件,它们拥有自己的物件</span><span  id=Layer9></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>不过这样有意义吗?它允许这些物件永远存在并使用中间层伺服器机器上可用的资源吗?每个执行的物件终究需耗用一些记忆体,使用执行绪,或许建立了一条到资料库的连线等等。若要让这个应用程式尽其可能具延展性,这表示在中间层要能够以最小等级的硬体设备,来支援大量的客户端。我们得确保每个物件只有在必要时才会使用这些资源。避免物件握住使用中的资源之时间过久,我们就可以让其它物件使用这些资源。特别是拥有大量客户端的应用程式,强制物件以此方式共享资源方可有效增进延展性。</span><span  id=Layer10></font></p><p><font size=2 color=#3c3c3c face=arial>为了让应用程式能够延展,它的物件必需共享资源</span><span  id=Layer11></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>为了让应用程式能够延展,它的物件必需共享资源</span><span  id=Layer12></font></p><hr><p><font size=2 color=#3c3c3c face=arial>若要知道运作的情况,思考一下一般的电话可让电话中心的员工处理。假想顾客希望转帐两笔基金∶首先从帐户P转到帐户Q,然後从帐户R转到帐户S。当电话一来时,她告诉银行行员她的姓名,或许还提供一些资讯以验证身份。接下来顾客要求开始第一个转帐动作,叙述帐户P与Q的号码,以及转帐的金额,然後银行行员便进行这项操作。(事实上,客户端的软体可能会呼叫前面描述的MoveMoney method。)因为QwickBank的顾客遍及全国,而且公司的管理者要求电话中心的员工要亲切一些,银行行员便与顾客闲聊,询问顾客居处的城市的天气概况。接下来顾客给予第二次要转帐的帐户号码,然後员工再度呼叫MoveMoney。接着两方互道再见,电话便结束了。</span><span  id=Layer13></font></p><p><font size=2 color=#3c3c3c face=arial>这整个交谈动作可能持续大约五分钟。不过真正需要一个活动的物件执行在在中间层伺服器上的时间有多久呢?答案是不会超过几秒钟,只要这些时间就足够执行要求的两个交易。因为这个理由,为何要让一个专案为了整个员工、顾客的互动动作吃掉大部份的资源呢?特别是在设备最简陋的中间层伺服器上,又需要支援大量客户端的应用程式来说是不具任何意义的。</span><span  id=Layer14></font></p><p><font size=2 color=#3c3c3c face=arial>使用者使用的物件大部份的时间都在闲置状态</span><span  id=Layer15></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>使用者使用的物件大部份的时间都在闲置状态</span><span  id=Layer16></font></p><hr><p><font size=2 color=#3c3c3c face=arial>一个很明显的解决方案便是让执行在银行员工电脑上的客户端软体在进行每个转帐动作之前,明确地建立物件,然後在交易完成後释放这个物件。不过这将会让客户端的程式码变得复杂,同时也会增加大量的网路流量,以及机器的资源。更佳的解决方案就是COM+提供的及时启动(Just-In-Time,JIT)。</span><span  id=Layer17></font></p><font color=#3e72d7 face=arial size=4><b>JIT启动</span><span  id=Layer18></b></font><p><font size=2 color=#3c3c3c face=arial>JIT启动依赖一个事实,即COM runtime能拦截有设定使用JIT服务的物件所发出的每一个呼叫。图8-17显示一个概念示意图,描述客户端对受COM runtime管理的物件发出呼叫时的路径。就如</span><span  id=Layer19>&nbsp;<a target='_new' href=205.htm#>第五章</span><span  id=Layer20></a>&nbsp;所描述,从客户端的apartment所发出对物件的呼叫会先到proxy,然後传入stub。对於未设定元件来说,stub将会直接呼叫目标物件的method。不过对已设定元件(身为COM+应用程式一部份的元件)来说,stub呼叫COM runtime所提供的一个method,这就是runtime为何能够将自己插入呼叫路径的原因。最後Runtime依次呼叫目标物件上的真正method。</span><span  id=Layer21></font></p><p><font size=2 color=#3c3c3c face=arial>COM runtime拦截每个对设定元件发出的呼叫</span><span  id=Layer22></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>COM runtime拦截每个对设定元件发出的呼叫</span><span  id=Layer23></font></p><hr><br><center><a target=_new href=imagesh/8-17.gif><img border=0 src='imagesl/8-17.gif'></a></center></span><span  id=Layer24><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b>&nbsp;图8-17</span><span  id=Layer25>&nbsp;</b></font>呼叫存在於COM+应用程式的物件通常透过proxy与stub,然後在进入目标物件之前经过runtime。</span><span  id=Layer26></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>不过当method完成时,它很可能会呼叫SetComplete或SetAbort。若开启已设定元件JIT启动的功能(这对使用交易的元件是必须的),有些有趣的事就在此时发生。每当使用JIT启动的物件之method呼叫到IObject-Context::SetComplete 或IObjectContext::SetAbort後,接下来将控制权交给COM runtime,runtime便呼叫物件上的Release,然後物件便闲置(deactivated)了,不过客户端并不会直接看到这一点。闲置一个物件将会让结果看起来如图8-18∶客户端拥有一个proxy,它可以与stub沟通,stub再连结到COM runtime,不见的是物件本身。</span><span  id=Layer27></font></p><p><font size=2 color=#3c3c3c face=arial>COM runtime在物件呼叫SetComplete或SetAbort时便闲置了</span><span  id=Layer28></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>COM runtime在物件呼叫SetComplete或SetAbort时便闲置了</span><span  id=Layer29></font></p><hr><p><font size=2 color=#3c3c3c face=arial>不过客户端并没有察觉物件死亡了。它仍拥有指向proxy的介面指标,如平常一样,因此它可以快乐地呼叫物件的其它method。当这个呼叫到达伺服器时,COM tuntime将会注意到它没有任何物件可以处理这个呼叫,同时,它将建立这个类别的新实例,回到图8-17的状态。Runtime接着呼叫新物件的method,执行,然後或许也会呼叫SetComplete或SetAbort。COM runtime再度释放这个物件,而情况又回到图8-18所示。不到客户端呼叫物件的Release之前,不会释放掉proxy与stub。直到那时,客户端就可以继续进行method call,而COM runtime将会在必要时处理物件的启动与闲置动作。</span><span  id=Layer30></font></p><p><font size=2 color=#3c3c3c face=arial>当客户端呼叫一个闲置元件上的method时,COM runtime便建立此物件的新实例</span><span  id=Layer31></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>当客户端呼叫一个闲置元件上的method时,COM runtime便建立此物件的新实例</span><span  id=Layer32></font></p><hr><br><center><a target=_new href=imagesh/8-18.gif><img border=0 src='imagesl/8-18.gif'></a></center></span><span  id=Layer33><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b>&nbsp;图8-18</span><span  id=Layer34>&nbsp;</b></font>呼叫SetComplete或SetAbort的物件便闲置了,只留下stub与proxy。</span><span  id=Layer35></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>若要知道这个运作方式的具体概念,再度思考一下前面描述的电话中心例子。想像一下银行员工每天早上到公司时将电脑开机,然後启动这个客户端应用程式。因为我们假设Visual Basic客户端透过DCOM与中间层沟通,这个客户端可能会在启动时马上发行一个CoCreateInstance要求。如前所述,让物件再度存在。若我们假设虚构的银行员工能在两个帐户间进行转帐的工作,那麽他一整天都必须依赖相同的物件,使用这个物件来完成MoveMoney的要求。不过他并不知道,物件实际上在这一天之中早就被一再启动、闲置无数次了。</span><span  id=Layer36></font></p><p><font size=2 color=#3c3c3c face=arial>客户端可以依赖看起来一模一样的新物件继续许多不相关的交易</span><span  id=Layer37></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>客户端可以依赖看起来一模一样的新物件继续许多不相关的交易</span><span  id=Layer38></font></p><hr><p><font size=2 color=#3c3c3c face=arial>若使用者使用浏览器而不是Visual Basic客户端来发出要求,要求将会透过HTTP传送到中间层伺服器。在这个情况下,每个要求可能会导致一个ASP网页被执行,而这个ASP网页便会建立物件。不过通常物件在使用者发出的每个要求之间,将会被毁灭(不仅仅是闲置而已)。这是因为ASP网页是在接收到浏览器送过来的要求到达时开始执行,然後在要求执行结束时毁灭。在预设情况下,网页上建立的每个COM物件也会在网页执行完毕时毁灭。在这个情况下,电话中心一天中就不会用到相同的物件,而是为每个使用者发出的要求建立一个新的。</span><span  id=Layer39></font></p><p><font size=2 color=#3c3c3c face=arial>假设原始的Visual Basic客户端的范例情节如下∶银行员工坐在电脑前等待顾客的电话。客户端刚刚发行一个CoCreateInstance,因此它拥有指向物件的介面指标。当顾客的电话到来时,直到员工进行转帐动作,什麽事都不会发生。这将导致Visual Basic客户端呼叫位於中间层伺服器COM runtime管理的物件之method,此时物件已建立了。如前面章节所描述,这个method从一个帐户扣款,然後新增到别的帐户,接着呼叫SetComplete或SetAbort结束这个交易。当method将控制权交给COM runtime,runtime呼叫实作MoveMoney的物件之Release method,然後就被闲置了,接着method再度执行。当它完成时,物件已闲置,并释放它使用的所有资源。不管银行员工在电脑前面和这位顾客交谈多久,物件只在必要时存在(物件会占用资源),也就是说,只要在真正要执行method时才存在。</span><span  id=Layer40></font></p><p><font size=2 color=#3c3c3c face=arial>JIT启动允许物件在必要时才存在</span><span  id=Layer41></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>JIT启动允许物件在必要时才存在</span><span  id=Layer42></font></p><hr><p><font size=2 color=#3c3c3c face=arial>如前所描述,物件中的每个method都不需要以呼叫SetComplete或SetAbort做为结束。一个客户端可能会对一个物件进行多次的呼叫,然後只在最後呼叫的method中呼叫SetComplete或SetAbort。在这个情况下,物件在每个method call之後将不会被毁灭,也不会闲置。不过要了解若这个物件使用交易机制,若在指定的时间内没有呼叫SetComplete或SetAbort,交易的计时器将会让交易取消,然後毁灭物件。</span><span  id=Layer43></font></p><p><font size=2 color=#3c3c3c face=arial>对於没有使用交易机制的元件来说,可以关闭JIT启动。不过若元件的异动属性设定为需要新增、必需的,或支援时将会自动开启JIT启动。由於增加前面描述的延展性,你将可从中获益。因为交易性物件必需使用JIT启动,这些元件无法跨交易边界来维护记忆体中的状态资料。当交易结束时,物件便闲置,同时记忆体也释放掉了。在COM+中没有这种可能∶结束一个交易代表毁灭掉加入交易的物件维护在记忆体内之所有状态。</span><span  id=Layer44></font></p><p><font size=2 color=#3c3c3c face=arial>一个交易性COM物件内部不能跨交易边界维护状态</span><span  id=Layer45></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>一个交易性COM物件内部不能跨交易边界维护状态</span><span  id=Layer46></font></p><hr><p><font size=2 color=#3c3c3c face=arial>因为这个理由,有些人称这些从设定元件建立的物件为无状态物件。这并不是绝对正确的,因为这些物件有时可以在不同的method call之间保留一些状态,且它们并不是永远都需要使用JIT启动。不过它倒是描述了最常用的方法。</span><span  id=Layer47></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b> 附注</b></font><p><font size=2 color=#3c3c3c face=arial>因为这个理由,有些人称这些从设定元件建立的物件为无状态物件。这并不是绝对正确的,因为这些物件有时可以在不同的method call之间保留一些状态,且它们并不是永远都需要使用JIT启动。不过它倒是描述了最常用的方法。</span><span  id=Layer48></font></p><hr><p><font size=2 color=#3c3c3c face=arial>回顾在COM+中物件并不需要知道交易最後的结果,只知道它投票要进行确认还是取消。假设一个物件被允许跨交易边界维护状态资讯,然这个状态资讯反应出交易过程中的变动情形,如支票帐户的新馀额。现在假设物件呼叫SetComplete,投票决定确认交易。若交易真的取消了又会发生何事呢?物件不会得知这件事,同时所维护的状态资讯是不正确的。若物件使用这个状态来满足客户端下一个method call,或许是一个检查客户端帐户馀额的method call,这将会得到错误的结果。 结合的JIT起动与交易边界将会强制物件重新整理它的状态,增加正确执行的机率。这个结合的动作不仅增加了应用程式的延展性,也增加了应用程式的正确性。</span><span  id=Layer49></font></p><p><font size=2 color=#3c3c3c face=arial>遗失状态资讯,然後重新整理,可以协助应用程式更能正确执行</span><span  id=Layer50></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>遗失状态资讯,然後重新整理,可以协助应用程式更能正确执行</span><span  id=Layer51></font></p><hr><font color=#3e72d7 face=arial size=4><b>管理状态</span><span  id=Layer52></b></font><p><font size=2 color=#3c3c3c face=arial>虽然JIT启动真得让应用程式更具延展性、达到正确性,但无可否认的应用程式设计师的生活将变得更加困难。设计不维护内部状态的中间层物件之应用程式跟过去程式设计师习惯的设计方式全然不同。因此,使用JIT启动需要以新思维来思考物件的状态。</span><span  id=Layer53></font></p><p><font size=2 color=#3c3c3c face=arial>JIT启动需要管理状态</span><span  id=Layer54></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>JIT启动需要管理状态</span><span  id=Layer55></font></p><hr><p><font size=2 color=#3c3c3c face=arial>如有可能,使用这个服务的应用程式一点儿都不应该维护中间层状态。举例来说,前面描述的电话中心例子可能可以从顾客处取得交易所需的每项资讯,然後进行交易,并取得交易的结果。若每个交易都需要一个新的、不同的资讯,那麽就没有在中间层物件维护状态资讯的必要。</span><span  id=Layer56></font></p><p><font size=2 color=#3c3c3c face=arial>某些物件没有需维护的状态资讯</span><span  id=Layer57></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>某些物件没有需维护的状态资讯</span><span  id=Layer58></font></p><hr><p><font size=2 color=#3c3c3c face=arial>真正的生活很少会平顺没有大风大浪的。举例来说,假设QwickBank的电话中心应用程式允许顾客询问许多帐户的问题,而这些帐户可能储存在其它电脑上的不同资料库上。存取所有的资讯可能是一个很慢的过程。为的达到可接受的效能水平,这位顾客的第一个查询可能会到各台机器上读取所有的资讯,然後储存在单机上。稍後存取时能够较为快些,因为所需的资讯已马上可以读取了。</span><span  id=Layer59></font></p><p><font size=2 color=#3c3c3c face=arial>然而维护状态有时是必要的</span><span  id=Layer60></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>然而维护状态有时是必要的</span><span  id=Layer61></font></p><hr><p><font size=2 color=#3c3c3c face=arial>不过这些资讯该储存在哪里呢?它不能够无限期地维护在交易性物件中,因为状态资讯会在每一个交易完成後毁灭。在此存在许多可能性,如图8-19。</span><span  id=Layer62></font></p><br><center><a target=_new href=imagesh/8-19.gif><img border=0 src='imagesl/8-19.gif'></a></center></span><span  id=Layer63><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b>&nbsp;图8-19</span><span  id=Layer64>&nbsp;</b></font>当你使用JIT启动时,储存状态可以有许多不同的选择。</span><span  id=Layer65></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>中间层物件的其中一项选择便是在自己所属的交易结束时,将状态资讯回传给客户端。接着在下一个method call客户端就可以将状态资讯传回给物件。对於少量的状态资讯,这个解决方案是简单又有效率的,但是将许多资讯来来回回的在客户端与中间层机器间传递有很大的问题。这样的结果是,若状态资讯相当庞大时,将状态储存在客户端将会相当没有效率。</span><span  id=Layer66></font></p><p><font size=2 color=#3c3c3c face=arial>客户端可以为闲置的物件储存状态</span><span  id=Layer67></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>客户端可以为闲置的物件储存状态</span><span  id=Layer68></font></p><hr><p><font size=2 color=#3c3c3c face=arial>另一个选择便是善用这个事实∶受COM runtime管理的物件并不一定需要交易或JIT启动。若物件的异动属性是设定为不支援(Not Supported),且关闭JIT启动,或者物件不会做任何导致JIT启动的动作(如呼叫SetComplete),这个物件将永远不会被闲置。它可以建立其它的交易性物件,当他们的交易结束时,所有的物件都会进入闲置的状态,不过容可在交易的过程中储存状态。</span><span  id=Layer69></font></p><p><font size=2 color=#3c3c3c face=arial>交易性物件可以维持状态一段时间</span><span  id=Layer70></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>交易性物件可以维持状态一段时间</span><span  id=Layer71></font></p><hr><p><font size=2 color=#3c3c3c face=arial>另一个可能性是将状态储存在Shared Property Manager (SPM)。SPM是一个DLL,可载入一个行程中,与COM runtime和一个或多个已设定元件一起运作。物件可以将状态储存在SPM,然後传递一个参考(reference)回到它的客户端。当这个客户端下一回呼叫这个物件的某个method,它就将这个参考回传。新建立的JIT启动物件使用这个参考从SPM读取状态资讯。</span><span  id=Layer72></font></p><p><font size=2 color=#3c3c3c face=arial>SPM可以为一个交易性物件储存状态</span><span  id=Layer73></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>SPM可以为一个交易性物件储存状态</span><span  id=Layer74></font></p><hr><p><font size=2 color=#3c3c3c face=arial>虽然SPM很有用,但是它相当地简单。举例来说,它不能够加入交易中处理。若物件将状态储存在SPM,然後呼叫SetComplete,交易还是有取消的可能。若取消的事件发生时,储存在SPM的状态并不会复原。SPM并不会像资源管理者一样的运作。若储存的状态真的是这个交易中放在快取中资料的复本,如帐户馀额,则在交易取消後,馀额数字可能就不正确了。同样地,若客户端意外的当机,则清除SPM残留下来的状态资讯也是一件令人厌烦的工作。因为这些理由,SPM多半应用在S允许同一个行程中的物件来共享状态,而较不常用在储存闲置物件的状态。</span><span  id=Layer75></font></p><p><font size=2 color=#3c3c3c face=arial>储存状态资讯最後一项选择便是将它写到资料库。再次强调,客户端可能传递使用JIT启动的物件之一个键值(key),以便辨视要从资料库取回何种资讯。因为大部份的COM+应用程式都会存取一或两个DBMS,所以这通常是一个合理的选择。因为大部份DBMS将最近存取到的资料放到快取(cache),因此它的效率也是很快的。</span><span  id=Layer76></font></p><p><font size=2 color=#3c3c3c face=arial>交易性物件的状态资讯可以储存在资料库中</span><span  id=Layer77></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>交易性物件的状态资讯可以储存在资料库中</span><span  id=Layer78></font></p><hr><font color=#3e72d7 face=arial size=4><b>物件集区(Object Pooling)</span><span  id=Layer79></b></font><p><font size=2 color=#3c3c3c face=arial>不管它的好处是什麽,JIT启动看起来是没有效率的。为何要不断毁灭物件然後重新建立呢?事实上,情况通常没有这麽坏。重新建立物件的状态可能会很慢,这是因为要存取硬碟的缘故,不过重建物件的动作并没有想像中耗时。但是有些情况下,这并非真的。类似这样的情况,物件集区可能会非常的有用。</span><span  id=Layer80></font></p><p><font size=2 color=#3c3c3c face=arial>想像一下一个COM类别,它的method允许存取US利率波动的历史记录。假设每回从这个类别建立一个物件都必须从大型资料库读取出历史性资料到记忆体中,则一个动作就要花费许多时间。物件便要建立大量的状态资料,以便让所有欲存取资料的客户端使用。对於这个物件来说,平常的JIT启动将会变得很慢,因为每回建立物件时都必须进行昂贵的初始化动作。</span><span  id=Layer81></font></p><p><font size=2 color=#3c3c3c face=arial>密集进行初始化物件的动作会让JIT启动物件的过程变慢</span><span  id=Layer82></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>密集进行初始化物件的动作会让JIT启动物件的过程变慢</span><span  id=Layer83></font></p><hr><p><font size=2 color=#3c3c3c face=arial>物件集区能解决这个情况。若一个元件设定为能够置入集区(pool),当物件的method呼叫SetComplete或SetAbort的时候,便不需毁灭从这个元件建立起来的物件。有一种取代的做法是将同一个类别的其他物件放到集区中,而不建立这个类别的新实例。然後欲使用的物件便从集区中挑出,指定给客户端。</span><span  id=Layer84></font></p><p><font size=2 color=#3c3c3c face=arial>物件集区允许重复使用放在集区中的物件实例,而非建立一个新的</span><span  id=Layer85></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>物件集区允许重复使用放在集区中的物件实例,而非建立一个新的</span><span  id=Layer86></font></p><hr><p><font size=2 color=#3c3c3c face=arial>另一个重要的例子是能够拥有个别类别(per-class)状态的物件就是那些维护到资料库连线之物件。回顾</span><span  id=Layer87>&nbsp;<a target='_new' href=206.htm#>第六章</span><span  id=Layer88></a>&nbsp;所提,ODBC与OLE DB两者都能够自动提供资料库的连接共用区(connection pooling),允许物件避免多花费建立新连线的工夫。不过,只要任何客户端使用到放入集区的物件之任何一条连线,集区中物件也可以维护一条到资料库的开启连线。如此将允许程式设计师实作自己的连线共用区(connection pooling)机制。举例来说,你可以选择这样做,若你要应用程式在客户端任何的要求进来之前,先在集区中建立一些开启的连线。这是ODBC或OLE DB 集区机制无法办得到的。</span><span  id=Layer89></font></p><p><font size=2 color=#3c3c3c face=arial>拥有开启的资料库连线之物件可以放到集区</span><span  id=Layer90></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>拥有开启的资料库连线之物件可以放到集区</span><span  id=Layer91></font></p><hr><p><font size=2 color=#3c3c3c face=arial>然而集区拥有一些限制。为了要能置入集区,一个元件不能拥有执行绪黏着性(thread affinity)。也就是说,它必须能够在任何执行绪上执行。在Microsoft Visual Studio 6,这个限制使得Visual Basic无法建立能置入集区的元件。同样地,集区物件存取到的资源管理者无法自动加入交易之中,就如同普通的交易性物件一样。取代的做法是让集区物件的设计者撰写程式码,手动地将资源管理者加入交易中。</span><span  id=Layer92></font></p><p><font size=2 color=#3c3c3c face=arial>物件可以实作IObjectControl介面,以控制是否物件愿意放入集区。这个介面包含CanBePooled method,在物件置入闲置之前,COM runtime会呼叫这个method。若这个呼叫回传True,则元件组态为能够放入集区,这个物件的实例将会放到集区而不会被闲置。IObjectControl同样包含两个其它的method,Activate与Deactivate,在物件启动(activate)时,以及在物件被闲置(deactivate)之前,COM runtime分别会呼叫这两个method。如果愿意的话,即使没有使用物件集区的功能它们可以用在初始化以及清除的操作上。</span><span  id=Layer93></font></p><p><font size=2 color=#3c3c3c face=arial>物件可以控制是否置入集区</span><span  id=Layer94></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>物件可以控制是否置入集区</span><span  id=Layer95></font></p><hr><p><font size=2 color=#3c3c3c face=arial>物件集区对於那些获得大量的个别类别状态(per-class state),并进行维护的物件来说是相当有用的。同时也对任何使用这个类别建立起来的客户端很有帮助。不过对於维护特殊客户的专属的状态资讯之物件而言就不是很有用了。换句话说,你无法使用物件集区来维护个别客户端的状态,因为没有办法确保下一回客户端要求某个物件的实例时会取到与这回相同的同一个物件。实际上,这个特性将会增进某些应用程式的执行效能,但是并非对每种情况都会有用。</span><span  id=Layer96></font></p><p><font size=2 color=#3c3c3c face=arial>集区物件不能维护特定客户端的状态</span><span  id=Layer97></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>集区物件不能维护特定客户端的状态</span><span  id=Layer98></font></p><hr><font color=#3e72d7 face=arial size=4><b>并行服务(Concurrency Services)</span><span  id=Layer99></b></font><p><font size=2 color=#3c3c3c face=arial>&nbsp;<a target='_new' href=205.htm#>第五章</span><span  id=Layer100></a>&nbsp;描述COM apartment的概念,也就是能让多执行绪的应用程式使用COM的机制。因为COM+应用程式永远建立成DLL的形式,每个已设定元件都会在系统登录之中拥有执行绪模型。其中一项可能的值是Apartment,确保执行在特定的single-threaded apartment (STA)中之所有物件都会执行在apartment的这条孤单的执行绪上(译注∶因为STA中只有一条执行绪,所以才会形容它很孤单。)这就是典型的MTS元件所做的事,因此目前有许多应用程式都是以此方式运作。</span><span  id=Layer101></font></p><p><font size=2 color=#3c3c3c face=arial>已设定元件能使用Apartment执行绪模型</span><span  id=Layer102></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>已设定元件能使用Apartment执行绪模型</span><span  id=Layer103></font></p><hr><p><font size=2 color=#3c3c3c face=arial>然而如</span><span  id=Layer104>&nbsp;<a target='_new' href=205.htm#>第五章</span><span  id=Layer105></a>&nbsp;所提,Windows 2000引进一种新的apartment类型∶Neutral apartment,也称为thread-neutral apartment (TNA)。每个行程最多只能有一个TNA,但和STA、multi-threaded apartment (MTA)不同的地方在於,TNA中并没有存在任何的执行绪。能在这个apartment中执行的执行绪是必要的。进一步来说,许多已设定元件希望将系统登录的Threading Model属性值设定为Neutral (或设定为Both,这也允许在TNA中执行)而不要设定为Apartment。若要了解原因所在,就需思考apartment代表的意义以及COM+中context的出现所带来的影响。</span><span  id=Layer106></font></p><p><font size=2 color=#3c3c3c face=arial>大部份已设定元件最後都会使用执行绪模型而不是使用Apartment</span><span  id=Layer107></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>大部份已设定元件最後都会使用执行绪模型而不是使用Apartment</span><span  id=Layer108></font></p><hr><p><font size=2 color=#3c3c3c face=arial>STA陈述两个问题∶并行控制(concurrency control)与执行绪黏着性(thread affinity)。因为在STA中的所有物件都共享同一条执行绪,因此同时只能执行一个method。为了简化程式设计师的生活,让他们不用再关心并行存取物件的议题,STA同样也提供一种方式来确保程式码具有执行绪黏着性,这代表了使用Visual Basic撰写的程式永远会执行在同一条执行绪上。</span><span  id=Layer109></font></p><p><font size=2 color=#3c3c3c face=arial>不过从Visual Studio 7开始,Visual Basic便不再具有执行绪黏着性的困扰,因此也少掉一个使用STA的理由。若我们假设执行绪黏着性已不再是个无可避免的议题(此书撰写时这已不是真的了,但很快就会是了),而剩下来的问题便是控制物件的并行存取。不再依赖传统的apartment来解决这个问题,Windows 2000 COM runtime提供另一种抽象概念∶Activity。Activity第一次出现在MTS,而Windows 2000的activity仍旧和在MTS中的行为一致(不得不这样,不然程式码将会被破坏),不过他们可以做到更多事情。在COM+世界中,Activity是以context为基础的。</span><span  id=Layer110></font></p><p><font size=2 color=#3c3c3c face=arial>已设定元件可以使用Activity以进行并行控制</span><span  id=Layer111></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>已设定元件可以使用Activity以进行并行控制</span><span  id=Layer112></font></p><hr><p><font size=2 color=#3c3c3c face=arial>今天的COM中,一个apartment实际上是在单独行程中,一群context的特殊群组。若apartment为STA,一次只能够进行一个动作,这也就是说,在特定的时间点,任何STA的物件中只有一个method能够执行。一个activity在某些方面来说是相当简单的。如图8-20所示,然而一个单独的activity能包含多个apartment的context。若这些context全部处於相同的行程中,一个activity也同样能确保在这些context包含的物件中一次只可以执行一个method。举例来说,在图8-20中,在这个行程的TNA中有两个物件处於相同的activity,它能够确保在任何特定时间点,一次只能执行这些物件的其中一个method。假设执行绪黏着性不是个困扰,Activity对於并行控制的提供要比STA还要来得有弹性。</span><span  id=Layer113></font></p><p><font size=2 color=#3c3c3c face=arial>一个activity是一群context的集合</span><span  id=Layer114></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>一个activity是一群context的集合</span><span  id=Layer115></font></p><hr><br><center><a target=_new href=imagesh/8-20.gif><img border=0 src='imagesl/8-20.gif'></a></center></span><span  id=Layer116><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b>&nbsp;图8-20</span><span  id=Layer117>&nbsp;</b></font>一个activity是一群context的集合,它们能够进行流程控制</span><span  id=Layer118></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>如图8-20所示,执行在不同apartment的物件,如NTA与STA,或者是MTA,假设它们隶属於同一个activity时,同样也能让它们的工作同步(synchronize)执行。然而,其中有一件事让activity比apartment来得有用,这就是一个单独的activity可以包含执行在多台机器上不同行程中的context。图8-21解释了这个情况,展示两台不同的机器上包含四个物件的一个activity。这些物件是执行在叁个不同的context中,每个物件则位处於不同类型的apartment中,然而COM runtime已经尽其所能来确保这个activity下所有的呼叫都能同步执行。虽然当context存在於不同的行程时,不可能让Activity内多个method能够同时执行,不过在activity内所有的呼叫都是同步的。</span><span  id=Layer119></font></p><p><font size=2 color=#3c3c3c face=arial>在一个activity的物件能执行在不同机器上的不同行程中</span><span  id=Layer120></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>在一个activity的物件能执行在不同机器上的不同行程中</span><span  id=Layer121></font></p><hr><br><center><a target=_new href=imagesh/8-21.gif><img border=0 src='imagesl/8-21.gif'></a></center></span><span  id=Layer122><center><table border=0 ><td align=center><font color=#3c3c3c face=arial size=2><font size=2 face=arial color=#3e80d7><b>&nbsp;图8-21</span><span  id=Layer123>&nbsp;</b></font>一个activity可以横跨行程与机器边界</span><span  id=Layer124></td></table></font></center><p><font size=2 color=#3c3c3c face=arial>物件执行在哪个activity,以及是否它执行在某个activity中全都依赖於元件的同步处理(synchronization)属性内含值。就像已设定元件的其它属性一样,这个属性可以使用元件服务管理工具进行设定。这个属性的四个可能值就好像异动属性的值∶</span><span  id=Layer125></font></p><font size=2 color=#3c3c3c face=arial><ul><font size=2 face=arial color=#3c3c3c><li><font size=2 face=arial color=#3e80d7><b>&nbsp;需要新增</span><span  id=Layer126>&nbsp;</b></font>(</span><span  id=Layer127><font size=2 face=arial color=#3e80d7><b>&nbsp;Requires New</span><span  id=Layer128>&nbsp;</b></font>) 从设定为这个值的元件所建立的物件之同步处理(synchronization)属性将永远会要求COM runtime建立一个新包含此物件的新activity。</span><span  id=Layer129></li><br></font><font size=2 face=arial color=#3c3c3c><li><font size=2 face=arial color=#3e80d7><b>&nbsp;必需的</span><span  id=Layer130>&nbsp;</b></font>(</span><span  id=Layer131><font size=2 face=arial color=#3e80d7><b>&nbsp;Required</span><span  id=Layer132>&nbsp;</b></font>) 若物件建立者的同步处理属性已设定为这个值,且已为一个activity的一部份,这个物件将会加入这个activity。若建立者不存在於任何activity,则COM runtime将会为物件开始一个新activity。</span><span  id=Layer133></li><br></font><font size=2 face=arial color=#3c3c3c><li><font size=2 face=arial color=#3e80d7><b>&nbsp;支援</span><span  id=Layer134>&nbsp;</b></font>(</span><span  id=Layer135><font size=2 face=arial color=#3e80d7><b>&nbsp;Supported</span><span  id=Layer136>&nbsp;</b></font>) 这个值会让物件继承建立者的行为。若建立者为某个activity的一部份,这个物件将会加入这个activity。若建立者不为某个activity的一部份,这个物件将会执行在没有并行存取保护的环境中。</span><span  id=Layer137></li><br></font><font size=2 face=arial color=#3c3c3c><li><font size=2 face=arial color=#3e80d7><b>&nbsp;不支援</span><span  id=Layer138>&nbsp;</b></font>(</span><span  id=Layer139><font size=2 face=arial color=#3e80d7><b>&nbsp;Not Supported</span><span  id=Layer140>&nbsp;</b></font>) 不管建立者的行为为何,同步处理属性设定为这个值的物件永远不会成为某个activity的一部份。</span><span  id=Layer141></li><br></font><font size=2 face=arial color=#3c3c3c><li><font size=2 face=arial color=#3e80d7><b>&nbsp;停用</span><span  id=Layer142>&nbsp;</b></font>(</span><span  id=Layer143><font size=2 face=arial color=#3e80d7><b>&nbsp;Disabled</span><span  id=Layer144>&nbsp;</b></font>) 这个值指示COM runtime在决定要将新物件放在哪个context时,应该忽视元件的同步处理属性的设定。</span><span  id=Layer145></li><br></font></ul></font><p><font size=2 color=#3c3c3c face=arial>一个已设定元件的同步处理(synchronization)属性决定元件如何使用activity</span><span  id=Layer146></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>一个已设定元件的同步处理(synchronization)属性决定元件如何使用activity</span><span  id=Layer147></font></p><hr><p><font size=2 color=#3c3c3c face=arial>对於使用交易、JIT启动,或者是执行在一个STA的物件来说(涵盖了COM+应用程式大多数的元件),Activity是用来保护同时存取物件时必要的机制,它们是不能被关闭的。在COM+应用程式中的物件若不使用交易或JIT启动,并且能执行在MTA或TNA上,则它们拥有更多的选项。透过已设定元件的同步处理属性,便可能使用activity来控制同时存取物件的动作,而不需依赖STA。虽然STA仍旧是个可运作的解决方案,减少执行绪黏着性的需求,以及Context数量的增加让activity成为控制同时存取多个COM物件更具吸引力的方案</span><span  id=Layer148></font></p><p><font size=2 color=#3c3c3c face=arial>使用交易或JIT启动的物件必需使用Activity</span><span  id=Layer149></font></p><hr><font face=Arial Black color=#3e77d7 size=3><b></b></font><p><font size=2 color=#3c3c3c face=arial>使用交易或JIT启动的物件必需使用Activity</span>

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -