首页 / 软件开发 / .NET编程技术 / WF从入门到精通(第十七章):关联及本地主机通信(上)
WF从入门到精通(第十七章):关联及本地主机通信(上)2010-06-03 cnblogs GuoYong.Che学习完本章,你将掌握:1.了解工作流关联(correlation)以及在什么地方必须去使用它、它为什么是重要的2.使用工作流关联参数(correlation parameters)3.生成并使用相关的本地通信服务贯穿本书你看过的应用程序普遍都是基于单一相同架构的,通过WF的支持在工作流实例中执行任务。这些都是在应用程序和它的工作流实例间进行一对一的通信。假如你和一个工作流实例进行通信,你这样做保证了无论以任何方式在应用程序和工作流之间传送数据都不会被混淆。一个应用程序对应一个工作流。但是至少有一种情况也是有可能的,这是应用程序和工作流在同一个应用程序域(AppDomain)中执行的时候。你单独的一个应用程序会调用同一个工作流的多个副本。来回传送数据会发生什么呢?显然,有些人需要了解工作流和哪些数据协同工作的。通常我们不能混淆并要进行匹配比较。一旦创建了工作流实例并入队执行后,如果它绑定到一个指定的数据标识符,用工作流对不同的数据标识符进行信息的处理可能存在数据完整性的问题。其实,WF提供了一些内部簿记来帮助我们防止数据完整性的问题。在WF术语中,它被叫做关联(correlation),WF提供了非常强大的关联支持但它也很容易地使用。宿主和工作流的本地通信在我们进入关联的论题之前,让我们简要地回顾一下宿主和工作流的整个通信过程。在第8章“调用外部方法和工作流”中,介绍了CallExternalEvent活动并使用了一个本地通信服务来把数据从工作流发送到宿主应用程序中。在第10章“事件活动”中,使用了HandleExternalEvent活动来进行相反过程的处理:宿主也能把数据发送到工作流中。不论数据以哪种方式进行传送,我们首先都要创建一个接口。接口中的方法注定最终会成为CallExternalEvent活动,而接口中的事件则最终会成为HandleExternalEvent活动。我们使用wca.exe工具来为我们生成这些基于我们的接口的自定义活动。(我们也可以直接使用CallExternalEvent活动和HandleExternalEvent活动,它提供出要处理的每一个接口、方法或者事件,但是在我们的工作流中创建自定义活动是我们所强烈推荐的。)随着手头有了接口,我们然后就创建了一个本地服务并把它插入进了工作流运行时中,让它去管理我们的本地通信需求。本地服务由一个数据连接器和一个服务类组成。当应用程序需要发送数据到工作流中时,它需要得到这个来自工作流运行时的服务,然后激发由接口提供的事件。假如你把该事件处理器(event handler)拖进了工作流中并在适当的时候调用了该事件的话,你的工作流运行时会处理这些事件。另一方面,对本地通信服务来说,工作流却没有查询工作流运行时的必要。拖拽一个CallExternalMethod活动到你的工作流的处理路径中以后,在数据抵达的时候会自动通知宿主——这里再次假设宿主应用程序把一个接收数据事件的事件处理程序(event handler)连接到了本地通信服务上。工作流运行时保持工作流实例和本地通信服务以及宿主应用程序之间的联系。关联再次回味上一段内容。工作流实例不需要到处搜寻和宿主应用程序进行通信的服务。但是宿主应用程序还是需要查询本地通信服务。尽管如此,在某种程度上,由于宿主和工作流运行时之间交互的性质,处理过程也要强调宿主应用程序和工作流实例之间的一对多的关系。宿主应用程序需要识别出它想和哪一个工作流实例进行通信,因为可能有很多个选择。但是,一个工作流实例却没有这样的选择:因为它只可能属于一个宿主应用程序。宿主为了数据通信总是要通过查询工作流运行时来获取服务,本地通信服务正是一个你或许想去访问的服务之一。相反的过程无疑也是同样的。工作流被绑定到本地通信服务上而不用关心宿主应用程序的身份,这是架构设计上的必然结果,因为一个工作流实例只能属于一个宿主应用程序(它们之间是一对多的关系),它不可能属于一个以上的应用程序,所以不需要识别出应用程序的身份。综上所述,工作流运行时由此为工作流实例提供了本地通信服务,工作流实例可随意地调用外部方法。那么,对于宿主来说,使用工作流实例的标识符来传送和其相关的数据流的这种方式可行吗?也就是说,假如你掌握了一个工作流实例,然后试图和工作流往返发送和接收数据,难道仅仅有了一个工作流实例的ID号还不能足够唯一地识别出工作流实例和其关联的数据吗?是的,假如你的数据流不是单一的数据流的话。因为在你的工作流中有多个数据路径进出。为此,关联诞生了。当你使用相关的工作流通信的时候,工作流运行时最终会为识别出我们谈到的工作流和数据所必需的大量信息创建一个存储容器。当宿主和工作流来回传送数据的时候需要咨询相关令牌(correlation token),假如相关令牌指明了两边的会话是同步的,则意味着正确的工作流实例和绑定的活动正在和正确的一批数据进行通信,能继续进行通信。但是,假如相关令牌指出一个问题,则工作流运行时就不允许继续进行数据通信并抛出一个异常。问题可能包括正使用一个不正确的工作流实例、正和错误的数据通信、调用了绑定到不同的相关令牌上的活动、或者试图在没有首先创建相关令牌的情况下发送数据。相关令牌由CorrelationToken类维护。当你拖拽CallExternalMethod或者HandleExternalEvent活动到你的工作流中的时候,假如关联被调用,你就需要指定一个相关令牌。相关令牌通过名称进行共享,因此从数据会话的观点来看,通过为超过一个以上的相关活动指定相同名称的相关令牌,你可有效地把这些活动绑定到一起。令牌的名称只不过是一个字符串,除了进行识别外它的值没有什么意义。为什么本书不更早介绍相关令牌呢?这是一个好问题。毕竟,我们在前面的工作中无疑已经使用过CallExternalMethod和HandleExternalEvent活动。答案是我们选择的是不去调用关联。关联在所有的情况下并不都是必须的,直到本章你才真正创建了这样的工作流。当你的应用程序和工作流实例之间是一对一的映射的时候,关联不是必须的,你可忽略它并享受由此带来的性能上的略微改进。即使当你的单一的宿主应用程序有多个工作流实例的时候,没有关联你也能正常工作。但是,当你使用关联的时候,WF会防止你在不经意间混淆数据,在许多情况下,这是一个非常可取的特性。为了激活关联的使用基础,当你创建你的宿主通信接口的时候你要使用一个特定的基于WF的特性。一个好消息是处理执行宿主通信不会由此改变很多,但是在你的工作流上产生的效果却是激动人心的。