Statefinalization /初始化活动仅在叶状态上运行

时间:2009-11-25 12:26:40

标签: recursion workflow workflow-foundation finalizer state-machine

我正在尝试让我的Windows状态机工作流程与最终用户进行通信。我试图在StateActivity中实现的一般模式是:

StateInitializationActivity:向用户发送消息,请求回答问题(例如“您批准此文档吗?”),以及...的上下文 ... EventDrivenActivity:处理用户发送的答案
StateFinalizationActivity:取消消息(例如撤回文件,不再需要批准)

如果StateActivity是“叶子状态”(即没有子状态),这一切都可以正常工作。但是,如果我想使用递归的状态组合,它就不起作用。对于非叶状态,StateInitialization和StateFinalization不运行(我通过使用Reflector检查StateActivity源代码来确认此行为)。 EventDrivenActivity仍在监听,但最终用户不知道发生了什么。

对于StateInitialization,我认为解决这个问题的一种方法是用EventDrivenActivity和零延迟计时器替换它。我对如何处理StateFinalization感到困惑。

那么 - 有没有人对如何让State Finalization Activity始终运行有任何想法,即使对于非叶状态也是如此?

3 个答案:

答案 0 :(得分:1)

不幸的是,“嵌套状态”的结构是包含“子”的“父”之一,设计者UI重新强化了这个概念。因此,思考你的思维方式是非常自然和直观的。不幸是因为错了。

真正的关系是“一般” - >之一“具体”。它实际上是一种层次结构。考虑一种更为熟悉的关系: -

public class MySuperClass
{
    public MySuperClass(object parameter) { }
    protected void DoSomething() { }
}

public class MySubClass : MySuperClass
{
    protected void DoSomethingElse() { }
}

此处MySubClassDoSomething继承SuperClass。以上虽然被打破,因为SuperClass没有默认构造函数。 SuperClass的参数化构造函数也不会由SubClass继承。实际上,从逻辑上讲,子类永远不会继承超类的构造函数(或析构函数)。 (是的,有一些神奇的布线默认构造函数,但这比实质上更多的糖)。

类似地,包含在另一个StateActivity中的StateAcivities之间的关系实际上是包含的活动是容器的特化。每个包含的活动都继承了容器的事件驱动活动集。但是,每个包含的StateActivity都是工作流中与任何其他状态相同的第一类离散状态。

包含活动实际成为一个抽象,它不能转换为,并且重要的是没有真正的概念转换到另一个状态“内部”的状态。通过扩展,没有留下这种外部状态的概念。因此,没有包含StateActivity的初始化或完成。

设计器的一个怪癖允许您添加StateInitialization和StateFinalization,然后将StateActivities添加到状态。如果你尝试它,那么设计师的另一种方式就不会让你,因为它知道初始化和终结永远不会运行。

我意识到这实际上并没有回答你的问题而且我不愿意在这种情况下说“它无法完成”,但如果可以的话,那将会有点hacky。

答案 1 :(得分:0)

好的,所以这就是我最终决定做的事情。我创建了一个自定义跟踪服务,用于查找与进入或离开与最终用户进行通信所涉及的状态相对应的活动事件。输入状态时,此服务将用户的决策输入数据库,并在状态保留时将其删除。用户可以查询数据库以查看工作流正在等待的决策。工作流使用EventDrivenActivity中的ReceiveActivity侦听用户响应。这也适用于父母'superstates'的决定。这可能不是“跟踪服务”的目的,但它似乎有用

答案 2 :(得分:0)

我想到了另一种解决问题的方法。最初,我想到的是,对于通信,我将使用WF 3.5中提供的WCF集成的SendActivity和ReceiveActivity。

然而,最后我得出结论,忽略这些活动并使用本地服务实现自己的IEventActivity更容易。 IEventActivity.Subscribe可用于向用户表明他们有回答的问题,IEventActivity.Unsubscribe可用于取消问题。这意味着不需要在State的inialization和finalization块中进行单独的活动。使用工作流队列手动完成消息路由,并将用户的响应添加到具有适当名称的队列中。我使用Guid作为队列名称,并在IEventActivity.Subscribe调用期间将它们传递给用户。

我使用MSDN中的“文件系统观察程序”示例来确定如何执行此操作。 我还发现这篇文章非常具有说服力:http://www.infoq.com/articles/lublinksy-workqueue-mgr