具体实施方式
本发明的原理涉及这样的机制:其中异步操作管理器允许组件以标准化的方式执行异步操作,而不考虑构造结合该组件的应用所使用的应用框架。这允许更容易地构造单个组件同时允许该组件执行异步操作,而不考虑使用多个应用框架中的哪一个来构造应用。
本发明范围内的实施例包括用于携带或其上存储有计算机可执行指令或数据结构的计算机可读媒质。这种计算机可读媒质可以是能由通用或专用计算机所访问的任何可用的媒质。例如、但不限制,这种计算机可读媒质可以包括物理的计算机可读媒质,比如RAM、ROM、EEPROM、CD-ROM或其它光盘存储器、磁盘存储器或其它磁性存储设备,或者可用于携带或存储期望程序代码装置的任何其它媒质,其中所述程序代码装置的形式为计算机可执行指令或数据结构,并能被通用或专用计算机所访问。
当在网络上或者到计算机的另一通信连接(或硬线、无线、或硬线和无线的组合)上传输或提供信息时,计算机把连接适当地视为计算机可读媒质。这样,任何这样的连接都被适当地称为计算机可读媒质。上述的组合也应被包括在计算机可读媒质的范围内。计算机可执行指令包括例如:使通用计算机、专用计算机或专用处理设备执行特定的功能或一组功能的任何指令和数据。计算机可执行指令可以是例如像汇编语言这样的二进制、中间格式指令,或者甚至是源代码。尽管不作要求,仍将以计算机可执行指令的一般上下文来描述本发明,比如由网络环境中的计算机所执行的程序模块。一般而言,程序模块包括执行特定的任务或实现特定的抽象数据类型的例程、程序、对象、组件、数据结构等等。
本领域的技术人员会理解,本发明可以在有许多种计算机系统配置类型的网络计算环境中实现,包括个人计算机、手提设备、多处理器系统、基于微处理器的或可编程的消费者电子设备、网络PC、小型计算机、大型计算机等等。本发明也可以在分布式计算环境中实现,其中由通过通信网络相连(或通过硬线连接、无线连接、或通过硬线和无线连接的组合)的本地和远程处理设备来执行任务。在分布式计算环境中,程序模块可以位于本地和远程存储器存储设备中。
图1说明了适当的计算环境,其中可以以计算机120的形式采用本发明的原理。计算机120包括处理单元121、系统内存122、及把包括系统内存122在内的各种系统组件耦合至处理单元121的系统总线123。
系统总线123可能是多种类型总线结构的任一种,包括内存总线或内存控制器、外围设备总线、及使用任一多种总线结构的本地总线。系统内存包括只读内存(ROM)124和随机存取内存(RAM)125。基本输入/输出系统(BIOS)126可以被存储在ROM 124中,其包含例如在启动期间帮助在计算机120内的元件间传输信息的基本例程。
计算机120还可以包括:用于向磁性硬盘139读写的磁性硬盘驱动器127;用于向可移动磁盘129读写的磁盘驱动器128;以及用于向诸如CD-ROM这样的可移动光盘131或其它光学媒质读写的光盘驱动器130。磁性硬盘驱动器127、磁盘驱动器128以及光盘驱动器130分别通过硬盘驱动器接口132、磁盘驱动器接口133和光盘驱动器接口134连到系统总线123。驱动器和它们相关的计算机可读媒质为计算机120的计算机可执行指令、数据结构、程序模块及其它数据提供了非易失性存储。尽管这里描述的示例性环境采用了磁性硬盘139、可移动磁盘129以及可移动光盘131,也可以使用其它类型的用于存储数据的计算机可读媒质,包括磁性盒带、闪存卡、数字化视频盘、贝努力盒带、RAM、ROM等等。
包括一个或多个程序模块的程序代码装置可以被保存在硬盘139、磁盘129、光盘131、ROM 124或RAM 125上,包括操作系统135、一个或多个应用程序136、其它程序模块137以及程序数据138。用户可以通过键盘140、指点设备142或其它输入设备(未示出)(比如麦克风、游戏杆、游戏板、圆盘式卫星天线、扫描仪等等)把指令和信息输入到计算机120中。这些及其它输入设备通常通过与系统总线123耦合的串行端口接口146连接到处理单元121。或者,输入设备可以通过其它接口相连,比如并行端口、游戏端口或通用串行总线(USB)。监视器147或另一显示设备也经由诸如视频适配器148这样的接口连到系统总线123。除了监视器以外,个人计算机一般包括其它外围输出设备(未示出),比如扬声器和打印机。
计算机120可以工作在网络化环境中,该环境使用与诸如远程计算机149a和149b这样的一个或多个远程计算机之间的逻辑连接。远程计算机149a和149b各可以是另一台个人计算机、服务器、路由器、网络PC、对等设备或其它公共网络节点,并且一般包括上述与计算机120有关的许多或全部元件,尽管图1中仅说明了存储器存储设备150a和150b以及它们相关的应用程序136a和136b。图1所述的逻辑连接包括局域网(LAN)151和广域网(WAN)152,这里作为示例给出而非限制。这种网络环境在办公室、企业范围计算机网络、企业内部网和因特网中是常见的。
当用于LAN网络环境中时,计算机120通过网络接口或适配器153与局域网151相连。当用于WAN网络环境中时,计算机120可以包括调制解调器154、无线链路、或者用于在诸如因特网这样的广域网152上构造通信的其它装置。调制解调器154可以是内置或外置的,它通过串行端口接口146与系统总线123相连。在网络化环境中,关于计算机120所述的程序模块或其部分可以被存储在远程存储器存储设备中。可以理解,所示网络连接是示例性的,也可以使用在广域网152上建立通信的其它装置。
虽然图1给出了本发明的适当操作环境,然而也可以在能够浏览网站的任何计算系统中采用本发明的原理。图1所述的计算系统仅是说明性的,只不过代表了其中可实现本发明原理的许多种环境的一小部分。在说明书和权利要求书中,“计算系统”被广泛地定义为能使用软件来执行一个或多个功能的任何硬件组件。计算系统的示例包括台式计算机、便携式计算机、个人数字助理(PDA)、电话、或者具有处理能力的任何其它系统或设备。
图2说明了层次结构200,其帮助描述本发明的原理并且无须处在任一特定的计算系统上。层次结构200包括多个应用201,包括应用201A到201H,还有许多用横向的省略号201I表示。这些应用一般代表软件应用。软件应用一般通过使程序设计者起草源代码而创建。于是,编译程序把该源代码编译成(或解释程序解释该源代码)计算机可执行指令,这些指令可由处理器读取并遵循。
面向对象的程序设计的一个好处在于:它能把独立构造的组件结合到应用中。组件是计算机可执行指令的离散集合,在被执行时实现一个或多个功能。组件可由其它软件组件或应用所调用。由于独立构造的组件可以仅仅通过一次函数调用被结合到应用中,因此每次应用要具有组件所提供的功能时无须重构组件。因而,面向对象的程序设计使应用程序设计者能结合他人的工作,从而使应用程序设计者能将注意力更集中于应用的更高级的特性,而不是限于已经由他人解决的详细操作中。作为重现设计和重新构造组件的替代,应用程序设计者仅需起草足够的代码使得应用对组件作出适当结构的函数调用,并且使应用可以正确地解释从组件接收到的函数调用。组件设计者一般文档化他们的规范,用于放置并接收函数调用以允许应用设计者这样做。
回过去参照图2,层次包括多个组件202,包括组件202A到202F,还有许多用横向的省略号表示。这些组件202代表这样的组件:可以构造它们以允许通过一组件创建机制、其后是重复的函数调用和返回机制,能够结合到应用中。
应用201可以用若干可用的应用框架204之一来构造。应用框架包括应用框架204A到204D,还有许多用横向的省略号204E表示。应用框架包括一环境和一组工具,其便于构造适当功能的软件应用。应用框架的示例包括WINDOWS Forms客户端用户界面(UI)程序设计框架、ASP.NET服务器端UI程序设计和HTTP框架、自由线程的控制台应用、嵌入SQL服务器中的应用、以及现在开发或可能在将来开发的框架。应用框架在本领域中通常也称为“应用模型”。
与通常可用的组件相比,通常可用的应用框架相对较少,而与通常可用的应用相比,通常可用的组件相对较少。图2中,为了说明该现象,示出比组件202更多的应用201,并且示出比应用框架204更多的组件202,然而应用201、组件202和应用框架204决不是常规的。
层次结构200还包括异步操作管理器203。如上所述,在涉及异步操作时,不同的应用框架有不同的线程和并发模型。异步操作是当应用层进程正在进行时在另一执行线程或某片硬件处进行到完成的操作。一些应用框架对于在完成时异步操作执行哪个线程没有任何限制。其它应用框架可能要求异步操作执行特定的线程,该特定线程与用于呈现用户界面的线程相同。还有其它应用框架会要求执行除了呈现用户界面所使用的线程以外的线程。还有一些会要求异步操作执行与启动异步操作的线程相同的线程。另外有一些对于以任何特定的线程返回没有任何要求,但要求操作“串行化”;也就是,在任何给定的时间仅进行一个操作。
通常,当构造一组件,该组件执行更希望在后台执行的异步操作(比如文件下载等等)时,组件自身需要包含特别对付应用框架的线程和并发模型的代码,所述应用框架用于构造其中可能结合该组件的硬件。因而,得花费了很大的力气来编写这种代码,尤其当组件可能被结合到正在使用多个应用框架之一构造的应用中时。更糟糕的是,可能已构造多个组件以寻址不同的框架。而且,即使为每个现有应用框架编写的组件一般都不能工作在新引入的应用框架中。
异步操作管理器203使用标准接口203A与组件202相接,使得组件无须特别寻址正在使用哪个应用框架。相反,组件仅仅使用标准接口203A向异步操作管理器放置一标准函数调用。同样,应用框架204可以使用标准接口203B与异步操作管理器203通信。
如上所述,层次结构200无须在相同的计算系统上实现。然而,直线211、212以及箭头221、222和223说明了应用201D、组件202C、异步操作管理器203以及应用框架204A之间的互连关系。为了说明本发明的原理,在本说明书的其余部分假定应用201D、组件202C、异步操作管理器203以及应用框架204A工作在相同的计算系统上,因此在系统内存中例示。图1中把这种计算系统的一例说明为计算机120,然而任何计算系统都会满足。
应用201D用应用框架204A构造,如互连线212表示。组件202C被结合到应用201D中,如互连线211所表示。在创建组件202C后,为了启动异步操作,组件202C经由标准接口203A向异步操作管理器203放置一标准函数调用222。应用框架204A或另一模块可以通知异步组件(如箭头221所表示):用于构造应用201D的硬件框架的标识,所述应用201D中结合了请求异步操作的组件202C。在异步操作完成后,异步操作管理器203通知组件202C有关异步操作完成,如箭头223所表示。
图3说明了一种方法300,它使至少一个组件以独立于应用框架的方式执行异步操作,所述应用框架用于构造其中结合该组件的应用。在图2的环境中,执行异步操作的组件是组件202C,而结合该组件的应用是应用201D。
方法300由异步操作管理器203实现。异步操作管理器从组件202C接收标准函数调用222(动作301),然后响应于所述标准函数调用而执行一功能性的、面向结果的步骤,用于以适用于应用框架的方式执行异步操作,即使以独立于应用框架的方式发出函数调用(步骤310)。该步骤可以包括用于实现该结果的任何相应的动作。然而,在所述实施例中,步骤210包括相应的非功能性动作211、212、213和214。
尤其,异步操作管理器203检测用于构造应用201D的应用框架204A,所述应用201D中结合了组件202C(动作311)。这可以通过接收标识应用框架204A的通知221来完成。该动作可以发生在异步操作执行前或执行期间的任何时刻。
异步操作管理器203还确定要响应于函数调用而执行的异步操作(动作312)。然后,异步操作管理器203按照用于构造应用的应用框架201D来执行异步操作,所述应用中结合了组件202C(动作313)。接着,当异步操作完成时,异步组件以按照线程和并发模型的方式向组件202C发出一通知223(动作314)。换言之,异步操作返回到适合所检测的应用框架的线程。根据线程和并发模型,这可以包括不加限制地返回到任何线程、返回到与呈现用户界面所使用的线程相同或不同的线程、返回到与启动异步操作所使用的线程相同的线程、等等。
描述了本发明的原理后,现在将参照代码示例来描述可以与异步操作管理器203相接的组件示例。示例组件包含可用于任何应用框架的几种方法,异步操作管理器203可以处理这些方法。下面还将提供异步操作管理器的代码示例。
下面的组件代码示例题为“WholesaleGeoduckPricer”,并且说明了异步操作管理器203的组件用途,该管理器在该代码示例中被称为“AsyncOperationManager”,粗体的元件特别与AsyncOperationManager有关。首先注意到这里实现的CalculatePriceAsync()的版本采用称为“状态”的状态对象。而且,“WholesaleGeoduckPricer”允许多个同时的操作在待命。AsyncOperationManager及有关的类直接从组件设计者的观点出发来作出这些多个同时操作实现的管理。
下面给出组件代码示例,为了简洁易懂添加了行编号。
1. using System.ComponentModel;
2. public class WholesaleGeoduckPricer:Component
3. {
4. public WholesaleGeoduckPricer()
5. {
6. onCompletedDelegate = new
AsyncOperationPostDelegate(CalculateCompleted);
7. }
8. public void CalculatePriceAsync(float kilos,object state)
9. {
10. AsyncOperation asyncOp =
AsyncOpeartionManager.CreateOperation(state);
11. someMorePrimitiveMethodTakingDelegate(kilos, asyncOp, some-
delegate-constructed-from-MyCompletionMethod);
12. }
13. public event CalculatePriceCompletedEventHandler
CalculatePriceCompleted;
14. protected void
OnCalculatePriceCompleted(CalculatePriceCompletedEventArgs e)
15. {
16. if (CalculatePriceCompleted !=null)
17. {
18. CalculatePriceCompleted(this,e);
19. }
20. }
21. private void MyCompletionMethod(AsyncOperation asyncOp)
22. {
23. decimal price=...
24. Exception exception=...
25. bool cancelled=...
26. CalculatePriceCompletedEventArgs e = new
CalculatePriceCompletedEventArgs(price, exception, cancelled,
asyncOp.UserSuppliedToken);
27. asyncOp .OperationCompleted(onCompletedDelegate,e);
28. }
29. private void CalculateCompleted(AsyncOperation asyncOp,object
operationState)
30. {
31. OnCalculatePriceCompleted((CalculatePriceCompletedEventArgs)
operationState);
32. }
33. private AsyncOperationPostDelegate onCompletedDelegate;
34.}
35.public class CalculatePriceCompletedEventArgs:AsyncCompletedEventArgs
36.{
37. public CalculatePriceCompletedEventArgs(decimal price,Exception e,bool
cancelled,object state):base(e,cancelled,state)
38. {
39. this.price =price;
40. }
41. public decimal Price
42. {
43. get
44. {
45. RaiseExceptionIfNecessary();
46. return price;
47. }
48. }
49.}
50.public delegate void CalculatePriceCompleteEventHandler(object sender,
CalculatePriceCompleteEventArgs e);
该组件可以工作在任何应用框架中。AsyncOperationManager和AsyncOperation表示了抽象点,其中应用框架在其下、组件在其上,底层的基本结构确保了在正确的时刻安装应用框架适当的对象。
行2到34定义了以C#语言编写的WholesaleGeoduckPricer组件,C#语言是一种微软公司.NET语言。这个例子及所有其它例子都是以C#语言编写的。行2是组件的标题行,并且把组件定义为公共(public)类。行4到7定义了一公共的WholesaleGeoduckPricer构造程序。行6构造了用于在完成时返回异步操作的委派。
行8到12定义了一种公共方法CalculatePriceAsync,其中定价所需要的期望的Geoduck的公斤数。同样也把用户状态传到该方法中。该用户状态用于区分关于CalculatePriceAsync的多个独立调用。行10创建但尚未开始异步操作,其实现是通过调用AsyncOperationManager.CreateOperation方法来创建AsyncOperation,标识该异步操作的“生存时间”。用户状态被传到CreateOperation中。该“生存时间”AsyncOperation转到异步运行的底层机制。该机制还接收一委派,用于在AsynchOperation完成时调用MyCompletionMethod()方法。最后,由于成功、失败或取消,MyCompletionMethod()可以在任意的线程上被调用,并且把生存时间传到其中。
该MyCompletionMethod建立了CalculatePriceCompletedEventArgs,然后在AsyncOperation上调用OperationCompleted,在方法委派中传递,以便在当前应用模型的正确线程/环境上运行。该方法是CalculateCompleted()。
AsyncOperation.OperationCompleted()函数做以下两件事:确保在适当的线程或并发环境中调用指定的回调函数(委派),以及有效地“结束”异步操作的生存时间。试图在调用OperationCompleted以后使用AsyncOperation会引发一例外。当上面内容导致CalculateCompleted()时,则处在正确的线程/环境,并且仅能从那里引发事件。
注意到这里可以支持多个待命的同步操作,因为AsyncOperation用调用来实现,而不是被保存为组件中的单个实例数据。传递信息的另一种选择是在该组件上维持一个生存时间的集合、并且检取它们以调用OperationCompleted()、此后立即从集合中删除它们。
这些内容得出一种设计,借此组件要求一种静态方法AsyncOperationManager.CreateOperation()来为它创建一个新的AsyncOperation,以及用于通信的必要方法放开该对象。同时,CreateOperation()通过经过注册的工厂(factory)进行调用而创建其对象,该注册工厂的工作是为该线程的当前应用模型创建一个新的“生存时间”。
下面说明了异步操作管理器203的公共可用的接口(方法和属性),其中为了简洁而添加了行号:
1.namespace System.ComponentModel
2.{
3. public class AsyncOperationManager
4. {
5. static AsyncOperation CreateOperation(object userSuppliedToken);
6. static AsyncOperationFactory CurrentFactory
7. {
8. get;
9. set;
10. }
11. static AsyncOperationFactory FreeThreadedFactory
12. {
13. get;
14. }
15. }
16.}
方法CreateOperation定义如下:
static AsyncOperation CreateOperation(object userSuppliedToken);
方法CurrentFactory定义如下:
1.static AsyncOperationFactory CurrentFactory
2.{
3. get;
4. set;
5.}
取得(get)和设置(set)方法影响了线程当前的AsyncOperationFactory。该工厂用于创建实际的AsyncOperation。仅有应用框架提供商调用这些方法。
下面定义了FreeThreadedFactory方法,这是一种创建总是在独立线程上运行的AsyncOperation的工厂:
1.static AsyncOperationFactory FreeThreadedFactory
2.{
3. get;
4.}
该方法访问用于创建自由线程的异步操作生存时间的工厂。
下面是使AsyncOperation引用上述代码实例的类定义(为了简洁添加行号):
1 public abstract class AsyncOperation
2.{
3. public AsyncOperation(object userSuppliedToken);
4. public object UserSuppliedToken{get;}
5. public void OperationCompleted(AsyncOperationPostDelegate d,
object arg);
6. public void Post(AsyncOperationPostDelegate d,object arg);
7. protected abstract void
OperationCompletedCore(AsyncOperationPostDelegate d,object arg);
8. protected abstract void Post(AsyncOperationPostDelegate d,
object arg);
9.}
下面的VB.NET代码说明了该模式的“用途”。第一行构造了一个新的WholesaleGeoduckPricer组件。第二行开始CalculatePrice操作,因为它是异步进行的因此被称为CalculatePriceAsyn。最后,在结束处的函数是“完成处理器”,在定价操作完成后,其用函数的结果来调用该函数。注意到该完成函数是被异步调用的,并且在应用正在运行的正确的线程/环境上被调用(为了简洁添加行号)。
1.WithEvents MyPricer as New WholesaleGeoduckPricer
2.MyPricer.CalculatePriceAsync(3.4,Nothing)
3.Sub Pricer_CalculatePriceCompleted(ByVal Sender as Object,ByVal e as
CalculatePriceEventArgs)
4. Handles MyPricer.CalculatePriceCompleted
5. MessageBox.Show(“Price is”+e.Price);
6.End Sub
因而,已经描述了一种程序设计模型,其中可以以独立于底层应用框架的方式来构造组件,所述应用框架用于构造其中结合了组件的应用。因而,本发明的原理能够允许在构造实现异步操作的组件时使软件更有效的发展,因为组件设计者无须明确在组件自身中解决可能的底层应用框架线程和并发模型。
本发明可以包含在其它特定形式中,而不背离其精神或基本特性。所述实施例应被视作说明性的而不是限制性的。因此,本发明的范围由所附权利要求指明,而不是由上述说明书指明。其范围内应包含所有变化,只要这些变化在权利要求等价物的意义和范围内。