状态机工作流的并行事件
在上一篇文章《MOSS多级审批工作流【StateMachine版】》中,有这样一个情景,我创建了两个任务,并且要等到这两个任务都完成后,根据其结果进行一些操作。在这一部分,我遇到一个问题,如何并行的处理这两个任务呢?
已知一个EventDrivenActivity不能跳转到一个以上的StateActivity中,所以我只能在同一个StateActivity中处理这两个任务。于是又引出一个问题,既然要并行的处理这两个任务,那么就得将OnTaskChangedActivity分别添加到不同的EventDrivenActivity中,那么如何在两个任务都被修改之后再进行操作呢?也就是说,如何在两个EventDrivenActivity都结束之后继续操作呢?
在上一篇文章中,我的方法是每一次修改任务之后,都维护一个bool值,然后在每个EventDrivenActivity的最后添加IfElseActivity来判断两个bool值是否都为TRUE,如果都为TRUE,再根据任务审批结果跳转到不同的StateActivity。
这种方法固然没有问题,但终究有些繁琐,而且,如果我们修改了流程,需要使IfElseActivity中某一分支跳转到新添加的StateActivity,那么就得到逐个EventDrivenActivity内部修改。
其实我们完全可以把这种方法再抽象一下,为什么说状态机工作流是“事件驱动”工作流呢?是因为每一个状态都依靠事件来决定下一步的流转方向。
就拿在SharePoint工作流中为用户创建任务为例,我们在StateInitializationActivity中添加CreateTaskActivity来创建任务,然后在EventDrivenActivity中添加OnTaskChangedActivity来接收任务被修改的事件,根据任务修改的结果来决定跳转到哪个StateActivity。
那么CreateTaskActivity和OnTaskChangedActivity又是什么原理呢?CreateTaskActivity其实是从CallExternalMethodActivity继承而来,而OnTaskChangedActivity是从HandleExternalEventActivity继承而来,这两个活动一个用来调用宿主的方法,一个用来接收宿主的数据(如果想了解这两个活动,请参见我翻译的《WF编程 – 本地通信事件》(1、2))。
CreateTaskActivity调用SharePoint Service提供的的CrateTask方法来创建一个任务,当用户修改了任务时,SharePoint Service就触发OnTaskChanged事件,工作流中的OnTaskChangedActivity捕获了此事件,进行处理,使得工作流可以继续进行。
再回来思考我们的需求,不就是希望在每一次任务修改之后都能触发一个共同的事件,在利用此事件判断是否所有任务都已经完成吗?
那么参照CreateTaskActivity和OnTaskChangedActivity的方式,我们只需要这样做就可以满足要求了,在每一次任务被修改后,使用CallExternalMethodActivity调用一个方法,这个方法当然不可能是SharePoint提供的了,这需要我们自己提供,这个方法只做一件事情,就是触发一个事件。接着我们在同一个StateActivity中再添加一个新的EventDrivenActivity,在其内部添加一个HandleExternalEventActivity来接收这个事件,接着再利用IfElseActivity来判断所有任务的处理结果并执行相应的跳转。
这样做的好处是把以前每个EventDrivenActivity中的IfElseActivity独立成为一个单独的部分,利用WF的本地通信服务,我们仍然可以实现每一次修改活动,都执行IfElseActivity,但如果需要修改跳转的目标StateActivity,再也不需要逐个修改了。
但是在这个示例中,我并没有直接用CallExternalMethodActivity和HandleExternalEventActivity活动,而是继承它们来得到两个自定义活动,为什么要这样做呢?
前边提到,CallExternalMethodActivity会调用一个方法,这个方法需要我们自己提供,那么我们就要编写相应的接口和实现这个接口的服务,最重要的是,我们必须在ExternalDataExchangehangeService中添加这个服务,然而SharePoint Service并不允许我们接触Workflow Runtime,好在如果开发自定义活动的话,在活动的Execute方法中,我们可以通过ActivityExecutionContext的相关方法获得ExternalDataExchangehangeService,然后为其添加自定义服务。
关于WF本地通信服务的机制和开发方法,请参见我翻译的《WF编程 – 触发事件与调用方法》(1、2、3)。
这篇逻辑混乱的说明文到此结束,各位朋友倘若看的不明白,那一定是我的文笔太差,下载源码一看便能明白了。
点击下载源码(本例为MOSS多级审批工作流【StateMachine版】的修改版)
注:
- 请用Visual Studio 2008打开源码
- 需要SharePoint Service支持
- 编译之后请手工将WindStyle.WindowsWorkflow.Activities.dll添加到GAC




Windie Chai @ 豆瓣
windiechai @ Twitter
windiechai @ 新浪微博
haha …
很容易饶晕人的哦. ..
呵呵 ….还好. ..WF或MOSS 流程我都玩过…
要不然 可就真晕啦. ..
@AA本报
绕吧,逻辑混乱吧,哈哈。
@Windie Chai(笑煞天)
一般人看不懂~~呵呵
@veter
唉,我越是想把它解释的非常通俗,就发现它越是绕。
看来��的文笔一般啊。
��好很清晰 ^_^
最新的 SharePoint Service 那里有下载,中文版的最好;
@曲滨*銘龘鶽
微软的官方网站应该有下载,最新版本是SP1加一些补丁。
支持
这两天回家试验了一下,方法是可行的;不过
有些问题还是没解决;
如果是 3、4、5 级别都是同步的怎么办?
博主的例子就一层的同步
3级别审批:Task3 Task4
假设 Task3 Task4 就是 MOSS多级审批工作流【StateMachine版】v1.1
第一图中第3级描述的 Task3 Task4 后面有追加了2行
如果是
3级别审批:Task3 Task4
4级别审批:Task5 Task6
5级别审批:Task7 Task8
这样的
3-5-7
4-6-8
就是说 Task3 执行完就可以执行 Task5 然后是 Task7 不用等待 Task4
Task4 也一样执行完就可以执行 Task6 然后是 Task8
7、8 都完成后同步;
这样的拿状态机如何实现???
–是要把 3-5-7 4-6-8 都放在一个 StateActivity 里吗?
这样的化可太郁闷了有点;
或者有什么好的办法吗?
–请博主赐教;
@曲滨*銘龘鶽
呃,如果实现你的要求的话,确实有些麻烦,目前还没有啥好方法,我们一起想想。
@曲滨*銘龘鶽也正在研究這個問題。
我也正在整状态机并行的问题,头都大了。。。
@一叶飘零确实是件麻烦的事情,呵呵。
有一个解决多级并行的方法,就是使用InvokeWorkflowActivity,调用一个新的顺序工作流……不过还没试过。
其实还有一个难题,实现一个父子表的审批流程:父表是一个审批流程,每个父表包含多个子表(数量不定),每个子表也有个审批流程,只有每个子表都被“批准”时,整个父表才会被“批准”(自动),而这个流程又是多级的。
这个我也想到一解决方案,其实就是父子两个工作流之间的通信和操作,当每个子表到达“批准”时,都要调用外部一个方法去测试下是否父表下的所有子表都ok了,如果是就触发一个事件驱动父表,否则什么都不做。
然而实际使用工作流时,我用的都是纯xoml定义的(基��自定义的工作流类),然后给用户提供一个web编辑器能够改变工作流的流程和规则。所以如何使上面的并行方案成为可用户可编辑方案,才是真正的挑战。今天思考了一天父子表审批的可编辑性,得到了一个答案,不过在准备实施前被告知这个先不用做了。想想也罢了,毕竟目前的WF局限性是相当大的,到4.0时一切都会是全新的,所以现在还是别自讨苦吃了,哈。