本文主要介绍WF中状态机工作流的基础知识,状态机工作流和顺序型工作流不同。顺序型工作流一般是比较固定的,可预测的,和系统交互的时候比较多。而状态机工作流一般是不可预测,和人的交互会比较多一些,一般有回退流程的时候使用状态机工作流会比较好一点,如何正确的选择顺序型工作流还是状态机工作流是十分重要的。
StateMachineWorkflowActivity是状态机工作流的基类,StateActivity内可以接受多个EventDrivenActivity,一个StateInitializationActivity和一个StateFinalizationActivity。还可以包含SetStateActivity,StateActivity他们之间的关系如下图:
你的状态机工作流肯定要包含很多状态,那从哪一个开始呢,StateMacnineWorkflowActivity有一个InitialStateName属性,这个属性可以设置初始的状态点。还有一个CompletedStateName属性,表示状态机工作流完成的,如果哪个状态被设置了这个属性,这个状态就不能包含任何的子活动了。这个属性不是必须设置的,是可选的。除了这两个状态其他就都是过程状态结点了。一般每个结点都会使用SetState设置下一个状态,如果没有设置的话,当所有的EventDrivenActivity执行完成后流程在当前挂起。
一:实现一个状态机工作流的例子
1.我们就已开小汽车为例子来说明,当我们开车的时候车就会有很多状态,比如未启动,运行,倒车等等状态。这些状态之间不是随便可以转换的,下面开始我们的例子,首先定义本地服务的接口,代码如下(ICarService.cs):
[ExternalDataExchange] public interface ICarServices { event EventHandler<ExternalDataEventArgs> StartEngine; event EventHandler<ExternalDataEventArgs> StopEngine; event EventHandler<ExternalDataEventArgs> StopMovement; event EventHandler<ExternalDataEventArgs> GoForward; event EventHandler<ExternalDataEventArgs> GoReverse; event EventHandler<ExternalDataEventArgs> LeaveCar;
event EventHandler<ExternalDataEventArgs> BeepHorn;
void OnSendMessage(String message);
}
该接口定义关于操作小汽车的一些事件,OnSendMessage方法会给宿主程序放回一个Message。
2.我们定义CarService类来实现这个服务,代码如下(CarService.cs):
namespace CaryStateWorkflowLibrary { public class CarService : ICarServices { public event EventHandler<ExternalDataEventArgs> StartEngine; public event EventHandler<ExternalDataEventArgs> StopEngine; public event EventHandler<ExternalDataEventArgs> StopMovement; public event EventHandler<ExternalDataEventArgs> GoForward; public event EventHandler<ExternalDataEventArgs> GoReverse; public event EventHandler<ExternalDataEventArgs> BeepHorn; public event EventHandler<ExternalDataEventArgs> LeaveCar;
public void OnSendMessage(String message) { if (MessageReceived != null) { MessageReceivedEventArgs args= new MessageReceivedEventArgs( WorkflowEnvironment.WorkflowInstanceId,message); MessageReceived(this, args); } } public event EventHandler<MessageReceivedEventArgs> MessageReceived; public void OnStartEngine(ExternalDataEventArgs args) { if (StartEngine != null) { StartEngine(null, args); } } public void OnStopEngine(ExternalDataEventArgs args) { if (StopEngine != null) { StopEngine(null, args); } } public void OnStopMovement(ExternalDataEventArgs args) { if (StopMovement != null) { StopMovement(null, args); } } public void OnGoForward(ExternalDataEventArgs args) { if (GoForward != null) { GoForward(null, args); } } public void OnGoReverse(ExternalDataEventArgs args) { if (GoReverse != null) { GoReverse(null, args); } } public void OnBeepHorn(ExternalDataEventArgs args) { if (BeepHorn != null) { BeepHorn(null, args); } } public void OnLeaveCar(ExternalDataEventArgs args) { if (LeaveCar != null) { LeaveCar(null, args); } } } }
OnSendMessage方法通过MessageReceived事件将Message传给宿主程序,MessageReceived的有一个事件参数
MessageReceivedEventArgs,该类的代码如下(MessageReceivedEventArgs.cs):
[Serializable] public class MessageReceivedEventArgs : ExternalDataEventArgs { private String message; public MessageReceivedEventArgs(Guid instanceId, String message) : base(instanceId) { this.message = message; } public String Message { get { return message; } set { message = value; } } }
3.实现工作流,如下图:
该工作流中主要有5个状态,如上图中所示,NotRunningState为该状态机工作流的初始状态,DoneWithCarState为结束
状态,其他的都为过程结点,每个状态的左上角的图片可以标识状态的类别。
然后我们来设置每个状态的事件,如下图:
我们以NotRunningState状态的eventStartEngine为例,该EventDriven活动内包含三个子活动,一个
handleStartEngine用来接收事件,对小汽车进行操作,接着是一个callExternalMethod活动,用来返回相关的信息给
宿主程序,最后是一个SetState活动,来设置下一个状态。其他的状态都类似就不多介绍了。
不知道你有没有注意到该状态机工作流中有一个eventBeepHorn活动,并没有在任何一个状态里,这个是因为小汽车的鸣笛
动作不是一个状态,而且他在任何状态都可以做,所以我们把他放在外面,他包含一个handleBeepHorn和一个
callExternalMethod活动。
4.实现宿主程序,我们采用WinForm程序,如下图:
宿主程序中我们加载本地服务,在响应的动作中调用响应的事件,具体的代码在最后的下载中。
二:消除重复的事件处理
在我们上面的工作流中,状态MovingForwardState和状态MovingInReverseState这两个状态中接收的是同一个事件,
都是StopMovement事件,我们来对这部分做一下重构,我们在上面工作流的基础上添加一个新的状态名字叫做MovingState
,然后将MovingForwardState和MovingInReverseState状态拖到MovingState中作为他的子活动,并将MovingForwardState
或MovingInReverseState状态中的eventStopMovement拖到MovingState中作为子活动,将MovingForwardState和
MovingInReverseState状态中的子活动删除即可,最后完成如下图:
这样MovingState中的任何一个子活动都可以响应eventStopMovement中的事件,这里有一点要注意,从其他状态的
SetState依然指向原来的活动,即现在MovingState的子活动,而不是指向MovingState活动。现在再次运行程序和原来
的效果是一样的。
三:识别可用的事件
1.这部分要实现的效果如上面图片中的当我们点了StartEngine后,不可执行的动作按钮会是灰色的,我们使用WorkflowInstance
的GetWorkflowQueueData方法,根据该方法的返回值来做处理。我们在Form的构造函数添加如下代码:
btnStartEngine.Tag = "StartEngine"; btnStopEngine.Tag = "StopEngine"; btnForward.Tag = "GoForward"; btnReverse.Tag = "GoReverse"; btnStop.Tag = "StopMovement"; btnBeepHorn.Tag = "BeepHorn"; btnLeaveCar.Tag = "LeaveCar";
2.在状态机工作流中转向新的状态等待事件处理时,工作流会变成idle的状态,我们就在工作流的idle事件中来判断并设置响应的按钮是否启用,代码如下:
private void WorkflowRuntime_WorkflowIdled(object sender, WorkflowEventArgs e) { UpdateDelegate theDelegate = delegate() { EnableEventButtons(false); . ReadOnlyCollection<WorkflowQueueInfo> queueInfoData = instanceWrapper.WorkflowInstance.GetWorkflowQueueData(); if (queueInfoData != null) { foreach (WorkflowQueueInfo info in queueInfoData) { EventQueueName eventQueue = info.QueueName as EventQueueName; if (eventQueue == null) { break; } EnableButtonForEvent(eventQueue.MethodName); } } }; this.Invoke(theDelegate); }
每一个WorkflowQueueInfo对象都包含一个QueueName属性,他是EventQueueName对象的一个实例,该对象有一个
MethodName属性标识当前队列中调用的外部事件的名称,我们在EnableButtonForEvent中根据tag属性和该属性来判
断,代码如下:
private void EnableButtonForEvent(String eventName) { //如果控件的 Tag 属性和事件名称相同,就启用 foreach (Control control in this.Controls) { if (control is Button && control.Tag != null) { if (control.Tag.ToString() == eventName) { control.Enabled = true; } } } }
这样就可以了。
四:访问运行时信息
WF中提供的StateMachineWorkflowInstance类记录了当前实例的相关信息,下面的代码来获取当前的实例。
StateMachineWorkflowInstance stateMachine = new StateMachineWorkflowInstance
(workflowManager.WorkflowRuntime,instanceWrapper.WorkflowInstance.InstanceId);
这样我们就可以得到当前实例的一些信息了,比如CurrentState,CurrentStateName等,StateHistory可以获得状
态装换的历史记录,SetState方法可以设置下一个状态等,具体就参考MSDN吧。
主要代码下载:CaryStateMachineWorkflow
发表评论
-
平淡的2007
2007-12-24 08:04 817早上起来,送女朋友去公交车站,然后回来赶紧打开电脑,先 ... -
DreamSpark发布,高校学生免费使用Visual Studio 2008 Professional Edition 等微软软件
2008-02-20 13:23 1415今天上网无意中搜索到学生可以免费使用VS2008专业版,后来又 ... -
坚持学习WF(1):从HelloWorld开始
2008-04-04 16:30 892[置顶]坚持学习WF文章索 ... -
坚持学习WF(2):WF创作模式和设计时工具
2008-04-05 17:19 639[置顶]坚持学习WF文章索 ... -
坚持学习WF(3):WF框架概览
2008-04-08 07:27 783[置顶]坚持学习WF文章索 ... -
坚持学习WF(4):活动(Activity)和依赖属性(DependencyProperty)
2008-04-12 00:01 1148[置顶]坚持学习WF文章索引 活动(Activity) 活动 ... -
坚持学习WF(5):自定义活动(CustomActivity)
2008-04-13 15:25 929当WF提供的标准活动不能满足我们的需求的时候,我们就需要定义自 ... -
MOSS点滴(1):如何开发和部署feature
2008-04-16 21:35 835Features 是MOSS 2007以开箱即用的一套新功能, ... -
MOSS点滴(2):自定义Application Page
2008-04-19 20:07 844在MOSS中后台管理的页面都是Application Pag ... -
坚持学习WF(6):开发可复用的宿主程序
2008-04-21 21:45 695我们之前写工作流宿主 ... -
MOSS点滴(3):说说MOSS中的母版页
2008-04-25 21:15 1187MOSS中有两种页面:Site P ... -
MOSS点滴(4):实现Form认证
2008-04-29 21:12 705本文主要参考了网上的一些文章,但有些文章有些地方说的不是很明确 ... -
坚持学习WF(7):流程控制(Flow Control)
2008-04-30 18:10 839本文主要说说WF中和流 ... -
坚持学习WF(8):本地服务之调用外部方法
2008-05-09 08:17 761WF提供了一组核心服务 ... -
MOSS中的WebPart开发
2008-05-10 13:53 1060由于在asp.net1.1的时候asp.net中还没有webp ... -
坚持学习WF(9):本地服务之事件处理
2008-05-28 07:49 800[置顶]坚持学习WF文章索引 一:先来介绍两个活动 Even ... -
坚持学习WF(10):在工作流中使用关联
2008-06-01 13:03 692[置顶]坚持学习WF文章索 ... -
坚持学习WF(11):工作流通信与队列
2008-06-07 15:45 735[置顶]坚持学习WF文章索引 WF 提供的通信模型是构建于 ... -
MOSS中创建自定义内容类型
2008-06-12 20:23 1106一:简要介绍 某类内容 ... -
.NET中IDisposable接口的基本使用
2008-06-15 12:01 950首先来看MSDN中关于这个接口的说明: [ComVisible ...
相关推荐
坚持学习WF(15):状态机工作流 本文主要介绍WF中状态机工作流的基础知识,状态机工作流和顺序型工作流不同。顺序型工作流一般是比较固定的,可预测的,和系统交互的时候比较多。而状态机工作流一般是不可预测,和人...
坚持学习WF(15):状态机工作流 本文主要介绍WF中状态机工作流的基础知识,状态机工作流和顺序型工作流不同。顺序型工作流一般是比较固定的,可预测的,和系统交互的时候比较多。而状态机工作流一般是不可预测,和人...
学习这个实例,初学者可以了解到如何定义和管理状态机工作流的关键元素,如初始状态、终态、状态转换和触发器。此外,理解工作流的持久化、跟踪和监控功能也非常重要,这些特性使得工作流能够适应复杂的业务需求和...
开发者可以通过阅读源码,学习如何在实际项目中集成状态机工作流,理解如何处理复杂的业务流程,并掌握ASP.NET和WF的结合使用技巧。 总之,这个源码实例为学习者提供了一个实践状态机工作流和ASP.NET结合的宝贵机会...
WF支持四种主要的工作流模型:状态机、活动图、顺序流程和并行流程。 2. **简单状态机Workflow**: "简单状态机Workflow"通常是指一个工作流模型,它基于有限状态机的概念。在这种模型中,系统的状态通过一系列预...
在基于WF的工作流设计中,有几种基本的工作流类型:顺序工作流、状态机工作流、活动图工作流和业务规则工作流。顺序工作流按照预定义的顺序执行活动;状态机工作流根据事件触发状态变化;活动图工作流结合了顺序和...
"坚持学习WF(15)状态机工作流"介绍了状态机模型,这是一种常见于状态变化丰富的业务场景的工作流类型。 最后,"坚持学习WF(19)工作流线程"涵盖了WF中的并发和多线程概念,这对于理解和优化工作流性能至关重要。 总...
在状态机工作流中,首先需要定义各个状态(State)和它们之间的转换(Transition)。状态通过`StateActivity`类表示,每个状态可以包含一个或多个活动(Activity),这些活动在该状态下执行。转换则通过`State...
WF支持四种主要的工作流模型:顺序流程、状态机流程、活动图和业务规则流程,以适应各种业务场景。 在ASP.NET中集成WF,我们需要完成以下步骤: 1. **创建工作流项目**:首先,你需要在Visual Studio中创建一个新...
4. **持久化**: 为了能够在需要时恢复工作流,WF提供了持久化机制,可以将工作流实例的状态保存到数据库或其他持久存储中。 5. **工作流服务**: 如果结合WCF(Windows Communication Foundation),WF还可以创建...
在这个场景中,"wf状态机"可能指的是一个示例项目,用于演示如何在.NET环境中设计和实现状态机工作流。 状态机工作流是一种模型,它将业务过程表示为一系列状态,以及从一个状态到另一个状态的转换。每个状态代表...
2. **状态机工作流**:掌握状态机工作流的结构和设计原则,包括初始状态、最终状态、状态转换和事件触发。 3. **自定义设计器**:学习如何创建自定义活动设计器,包括UI元素的布局、交互逻辑和活动属性的编辑。 4....
通过对状态机工作流的学习和应用,可以提高开发者的工作效率和开发质量。 知识点: * WF 4.0 中状态机模式的支持 * 状态机工作流的基本概念 * StateMachin、State 和 FinalState 的角色 * Bookmark 的使用 * 业务...
通过本课程提供的PPT、视频和文档,你将获得实际操作的经验,学习如何创建和管理状态机工作流。示例代码和项目将帮助你加深理解,让你能够在自己的项目中灵活应用WF技术。无论你是初学者还是有经验的开发者,都能从...
其次,WF支持四种主要的工作流类型:顺序流程、状态机流程、并行流程和活动流程,分别对应不同的业务需求。顺序流程按照预定的顺序执行活动;状态机流程基于事件驱动,根据特定条件进行状态转换;并行流程可以同时...
WF支持多种工作流模式,如顺序、状态机、活动图和规则驱动的工作流。它还提供了持久化、跟踪和版本控制等特性,便于管理和维护工作流实例。 **LINQ(Language Integrated Query)**是.NET Framework 3.5引入的一个...
WF支持四种基本的工作流模型:顺序流程、状态机流程、活动网流程和复合活动流程。开发者可以根据实际需求选择合适的工作流模型来设计业务流程。 **WF的核心组件** 1. **活动(Activity)**:WF中的基本构建块,代表...
2. **状态机工作流**:如何构建和设计状态机模型的工作流,这种工作流常用于表示对象的不同状态及其转换。 3. **数据绑定和表达式**:学习如何在工作流中使用数据绑定和表达式来操作变量和活动参数。 4. **设计器...
状态机工作流是一种高效、灵活的编程模型,用于在软件应用中模拟和管理有固定顺序和规则的流程。...通过理解状态机工作流的基本原理和WF框架的使用,开发者能够设计出更加灵活、可维护的业务流程解决方案。
WF支持四种主要的工作流模式:顺序流程、状态机流程、活动图流程和业务规则流程。顺序流程是最基础的流程类型,按照预定义的顺序执行活动。状态机流程基于状态转换,适合处理事件驱动的场景。活动图流程以UML活动图...