cloudjun

导航

WF本质论 OpenSesame 芝麻开门代码

本文参考了包建强兄的“WF本质论 读书心得” (http://www.cnblogs.com/jax/archive/2008/02/21/1076632.html),他给出了部分的源代码, 我修改了一点,再添加上他没有给出的部分,就基本是一个可用的OpenSesame的源代码了。

首先肯定,WF本质论是本不可多得的好书。作者提出了许多令人耳目一新的见解,重点是用bookmark(也就是continuation的概念)来把本来会耗时很长并无端占用线程的操作解耦,通过delegate转换成可以在不同线程进程中执行的两部分,也就是作者所谓的thread agility & process agility.

第一章应该是全书的关键,理解了第一章就为理解WF的内部机制打下了坚实的基础。而作者用了一个贯穿了整个第一章例子,OpenSesame,芝麻开门来阐述他的观点,建议所有的读者都应该亲自动手来实现一下这个OpenSesame的例子,绝对可以加深理解。可惜的是,作者没有给出这个例子的完整代码,这里缺一块,那里少个角,掖着藏着让人很不舒服。Google了一下也没有全部的源码,所以我觉得花点时间把这个芝麻开门的代码写出来很有必要。需要声明的是,这个代码绝对不是什么最终的或是官方的版本,只是到目前为止我对本书第一章的理解而已。只是供大家参考,希望可以给正在看“WF本质论”的朋友有所帮助。

个人感觉关键的地方有这几点:

1)thread agility。 刚开始被书里的BeginReadLine例子误导,总想着用BeginInvoke/EndInvoke去神奇的实现长耗时操作并不占用线程(比如实现Console.ReadLine),后来才发现作者不是这个意思。作者把一个长耗时操作分成了两部分,上半部分(在代码中就是ProgramStatement.Run方法)只是创建一个bookmark,就是设定一个delegate,并没有其他的操作,也不需要异步,只是设定,然后上半部分就结束。下半部分(代码中的ContinueAt)就是本操作在获得了外界的输入后应该做的动作。奥妙就在于本来需要由这个长耗时操作占用一个线程进行的漫长而又无用的等待的工作(比如Console.ReadLine,需要等待用户输入),现在可以由主线程提供通知,从而使长耗时操作的下半部分得以进行下去。这样的好处就是,本来在等待输入的过程中的是要有个线程的,而现在就没了。

简言之,大家可以这样想,原先的情况是有一个主线程A,然后主线程A又生成了一个专门给长耗时操作用的线程B,在线程B里面需要Console.ReadLine,B得到输入后会进行一些操作,这样的话任何时候都会有两个线程。如果用了bookmark的方法,主线程A产生线程B调用bookmark的上半部分,然后线程B结束,这时我们在主线程中进行Console.ReadLine,得到了输入后我们再开一个线程B2,继续bookmark下半部分的调用,这样我们就节约了在等待用户输入时的一个线程。这就是作者所谓的thread agility。其实主线程是很忙的,实际运用中不可能停下来等待用户输入,它能做的应该是在它得到了用户输入/外界消息后(比如通过message queue),通知并调用bookmark的下半部分。

 2)书中的每个ProgramStatement(也就是WF的Activity)是通过BookmarkManager.Done()来启动的。

3) Passivate是实现process agility的手段,在代码中没有实现。

4)Binding. 细心的读者可能发现在书中作者没有给出怎么把上个ProgramStatement的输出赋值给下个ProgramStatement的代码,作者狡猾的用省略号表示了。因为这个绑定的动作发生在ProgramStatement实际的执行以前,如果我们没有做特殊处理的话,在执行的时候我们会得到null reference exception。在代码中就是PrintGreeting的Run方法内。在运行本程序的时候你会发现无论你输入什么,你总是得到"OKOK",因为我偷懒,没有用特殊方法去处理。我想到的一个不破坏整个bookmark逻辑的处理方法就是用.net AOP,在PrintGreeting的key和s属性上加上特殊的attribute,这样当这两个属性需要被用到的时候会去另外的ProgramStatement(Read,PrintKey)取。

5)主线程内,当有了Console.ReadLine的输入后,通过BookmarkManager.Resume去继续Bookmark的下半部的执行。相当于WF中,用WorkflowInstance.EnqueueItem()去继续流程。

6)ProgramHandle类,我觉得这个类有点鸡肋,没什么存在的必要。

 

附上OpenSesame的代码,欢迎大家共同讨论。

Code

posted on 2009-04-04 05:08  jun  阅读(2834)  评论(8编辑  收藏  举报