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

发布于 2024-08-12 13:37:08 字数 601 浏览 10 评论 0原文

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

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

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

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

那么,有谁知道如何让状态最终确定活动始终运行,即使对于非叶状态也是如此?

I am trying to get my Windows State Machine workflow to communicate with end users. The general pattern I am trying to implement within a StateActivity is:

StateInitializationActivity: Send a message to user requesting an answer to a question (e.g. "Do you approve this document?"), together with the context for...
...EventDrivenActivity: Deal with answer sent by user
StateFinalizationActivity: Cancel message (e.g. document is withdrawn and no longer needs approval)

This all works fine if the StateActivity is a "Leaf State" (i.e. has no child states). However, it does not work if I want to use recursive composition of states. For non-leaf states, StateInitialization and StateFinalization do not run (I confirmed this behaviour by using Reflector to inspect the StateActivity source code). The EventDrivenActivity is still listening, but the end user doesn't know what's going on.

For StateInitialization, I thought that one way to work around this would be to replace it with an EventDrivenActivity and a zero-delay timer. I'm stuck with what to do about StateFinalization.

So - does anyone have any ideas about how to get a State Finalization Activity to always run, even for non-leaf states?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

醉梦枕江山 2024-08-19 13:37:08

不幸的是,“嵌套状态”的结构是一个包含“子级”的“父级”,设计器 UI 重新强化了这一概念。因此,按照你的想法思考是非常自然和直观的。不幸的是,因为它是错误的。

真正的关系是“一般”->“一般”之一。 “具体的”。它实际上是一个等级结构。考虑一个更熟悉的这样的关系: -

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

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

这里MySubClassSuperClass继承了DoSomething。但上面的内容被破坏了,因为 SuperClass 没有默认的构造函数。另外,SuperClass 的参数化构造函数不会被 SubClass 继承。事实上,从逻辑上讲,子类永远不会继承超类的构造函数(或析构函数)。 (是的,默认构造函数有一些神奇的连接,但那是糖多于实质)。

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

包含的活动实际变成了抽象,它无法转换到,重要的是,不存在转换到另一个状态“内部”的状态的真正概念。推而广之,也不存在离开这样的外部状态的概念。因此,包含的 StateActivity 没有初始化或终结。

设计器的一个怪癖允许您添加 StateInitialization 和 StateFinalization,然后将 StateActivities 添加到状态。如果您以其他方式尝试,设计器将不会让您这样做,因为它知道初始化和最终化永远不会运行。

我意识到这实际上并不能回答你的问题,在这种情况下我不愿意说“这是不可能的”,但如果可以的话那就有点老套了。

Its unfortunate that the structure of "nested states" is one of a "parent" containing "children", the designer UI re-enforces this concept. Hence its quite natural and intuative to think the way you are thinking. Its unfortunate because its wrong.

The true relationship is one of "General" -> "Specific". Its in effect a hierachical class structure. Consider a much more familar such relationship:-

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

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

Here MySubClass inherits DoSomething from SuperClass. The above though is broken because the SuperClass doesn't have a default constructor. Also parameterised constructor of SuperClass is not inherited by SubClass. In fact logically a sub-class never inherits the constructors (or destructors) of the super-class. (Yes there is some magic wiring up default constructors but thats more sugar than substance).

Similarly the relationship between StateAcivities contained with another StateActivity is actually that the contained activity is a specialisation of the container. Each contained activity inherits the set of event driven activities of the container. However, each contained StateActivity is a first class discrete state in the workflow same as any other state.

The containing activity actual becomes an abstract, it can not be transitioned to and importantly there is no real concept of transition to a state "inside" another state. By extension then there is no concept of leaving such an outer state either. As a result there is no initialization or finalization of the containing StateActivity.

A quirk of the designer allows you to add a StateInitialization and StateFinalization then add StateActivities to a state. If you try it the other way round the designer won't let you because it knows the Initialization and Finalization will never be run.

I realise this doesn't actually answer your question and I'm loath to say in this case "It can't be done" but if it can it will be a little hacky.

九八野马 2024-08-19 13:37:08

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

OK, so here’s what I decided to do in the end. I created a custom tracking service which looks for activity events corresponding to entering or leaving the states which are involved in communication with end users. This service enters decisions for the user into a database when the state is entered and removes them when the state is left. The user can query the database to see what decisions the workflow is waiting on. The workflow listens for user responses using a ReceiveActivity in an EventDrivenActivity. This also works for decisions in parent ‘superstates’. This might not be exactly what a "Tracking Service" is meant to be for, but it seems to work

撩人痒 2024-08-19 13:37:08

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

然而,最后我得出的结论是,忽略这些活动并使用本地服务实现您自己的 IEventActivity 更容易。 IEventActivity.Subscribe 可用于向用户指示有一个问题需要他们回答,而 IEventActivity.Unsubscribe 可用于取消该问题。这意味着不需要在状态初始化和最终化块中进行单独的活动。消息路由是使用工作流队列手动完成的,并且用户的响应会以适当的名称添加到队列中。我使用 Guid 作为队列名称,这些名称在 IEventActivity.Subscribe 调用期间传递给用户。

我使用 MSDN 中的“文件系统观察器”示例来了解如何执行此操作。
我还发现这篇文章非常有启发性: http://www.infoq.com/articles/ lublinksy-工作队列-mgr

I've thought of another way of solving the problem. Originally, I had in mind that for communications I would use the WCF-integrated SendActivity and ReceiveActivity provided in WF 3.5.

However, in the end I came to the conclusion that it's easier to ignore these activities and implement your own IEventActivity with a local service. IEventActivity.Subscribe can be used to indicate to users that there is a question for them to answer and IEventActivity.Unsubscribe can be used to cancel the question. This means that separate activities in the State's inialization and finalization blocks are not required. The message routing is done manually using workflow queues and the user's response is added to the queue with appropriate name. I used Guid's for the queue names, and these are passed to the user during the IEventActivity.Subscribe call.

I used the 'File System Watcher' example in MSDN to work out how to do this.
I also found this article very insructive: http://www.infoq.com/articles/lublinksy-workqueue-mgr

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文