状态机是另外一种常见的工作流类型。它是以状态的变迁为驱动而进行业务流转的,是一定需要人为干预的,而不像顺序类型工作流那样可以按照事先设计好的业务流程一步一步依次执行下去。

一、状态机工作流范例

  State活动有三种状态类型:

  • 起始状态;
  • 业务逻辑过程状态;
  • 终止状态;

  在一个状态机工作流中起始状态和终止状态只能有一个。状态机工作流是从起始状态开始执行,在运行过程中通过业务员逻辑状态的变迁来进行工作流的流转,最终由终止状态标记工作流的结束。因此在状态机工作流设计界面上只能添加"State"状态活动,另外在该状态中还可以添加一个或多个"EventDriven(事件驱动活动)"。

  状态机工作流中大量使用HandleExternalEvent活动来接收应用程序的操作,从而改变工作流上运行表单的业务状态,因此需要定义一个接口程序作为工作流和应用程序之间沟通的桥梁。

  默认的状态机工作流界面图:

  

  在状态机工作流程序中需要指明哪个"State"活动是最先起始的活动,哪个"State"活动是最终结束的活动。

  

  可以通过点击"State"活动的右键菜单进行设置:

  

  通过拖动EventDriven活动左右两边的节点就可以建立状态间的变迁关系。

  工作流看似简单,实际上里面还要设置,双击每个EventDriven活动,为它添加一个HandleExternalEvent子活动,并将HandleExternalEvent子活动与接口项目中定义的事件依次绑定。

  

  Winform程序界面如下:

  

  其完成代码如下所示:

    public partial class Form1 : Form, ClassLibrary1.IEvent
{
public event EventHandler<ExternalDataEventArgs> Event1;
public event EventHandler<ExternalDataEventArgs> Event2;
public event EventHandler<ExternalDataEventArgs> Event3; public WorkflowRuntime workflowruntime;
private WorkflowInstance workflowinstance;
private ExternalDataExchangeService exterserv;
static AutoResetEvent waitHandle = new AutoResetEvent(false); //为了得到状态机工作流还运行中的变迁情况,例子使用了StateMachineInstanceStateHistory来获取状态机的状态。
//但使用"StateHistory"必须启动WWF工作流的"Persistence"和“Tracking”服务。
const string connectionTrackingString = "Initial Catalog=Tracking;Data Source=localhost;Integrated Security=SSPI;";
const string connectionPersistenceString = "Initial Catalog=SqlPersistenceService;Data Source=localhost;Integrated Security=SSPI;"; public Form1()
{
InitializeComponent(); workflowruntime = new WorkflowRuntime();
exterserv = new ExternalDataExchangeService(); workflowruntime.WorkflowIdled += OnWorkflowIdled;
workflowruntime.WorkflowCompleted += OnWorkflowCompleted; //分别创建"Persistence"与"Persistence"服务,并将它们加载到工作流的运行时容器Runtime中。
workflowruntime.AddService(new SqlTrackingService(connectionTrackingString));
WorkflowPersistenceService persistenceService = new SqlWorkflowPersistenceService(connectionPersistenceString);
workflowruntime.AddService(persistenceService); workflowruntime.AddService(exterserv);
exterserv.AddService(this); workflowruntime.StartRuntime(); Type wftype = typeof(WorkflowConsoleApplication1.Workflow1);
workflowinstance = workflowruntime.CreateWorkflow(wftype);
workflowinstance.Start();
} public void OnWorkflowIdled(object sender, WorkflowEventArgs e)
{
e.WorkflowInstance.TryUnload(); GetStateHistory addListItem = new GetStateHistory(GetStateHistorysync);
Invoke(addListItem, e.WorkflowInstance.InstanceId);
waitHandle.Set();
} public void OnWorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
{
Addstring addListItem = new Addstring(Addstringsync);
Invoke(addListItem, "结束");
waitHandle.Set();
} private void btn1_Click(object sender, EventArgs e)
{
Event1(null, new ExternalDataEventArgs(workflowinstance.InstanceId));
this.btn1.Enabled = false;
} private void btn2_Click(object sender, EventArgs e)
{
Event2(null, new ExternalDataEventArgs(workflowinstance.InstanceId));
this.btn2.Enabled = false;
} private void btn3_Click(object sender, EventArgs e)
{
Event3(null, new ExternalDataEventArgs(workflowinstance.InstanceId));
this.btn3.Enabled = false;
} //将每一步的状态变化取出来显示在列表中。通过"委托"代理啊在工作流的"OnWorkflowIdled"事件中被调用。
private delegate void GetStateHistory(Guid id);
public void GetStateHistorysync(Guid id)
{
StateMachineWorkflowInstance StateMachineInstance = new StateMachineWorkflowInstance(workflowruntime, id);
ReadOnlyCollection<string> states = StateMachineInstance.StateHistory;
for (int i = states.Count; i > ; i--)
{
this.listView1.Items.Add(states[i - ].ToString());
}
} private delegate void Addstring(string str);
public void Addstringsync(string str)
{
this.listView1.Items.Add(str);
}
}

  运行后可以看到其状态的切换:

  

二、StateInitialization和StateFinalization活动

  在上面的例子中,我们看到了WorkflowStarted与WorkflowCompleted两个事件,分别代表工作流的启动与结束。但在"State"状态活动的属性窗口中却找不到相应的开始和结束事件。WWF专门为"State"活动设计了两个子活动"StateInitialization"和"StateFinalization"来实现相应的功能。

  状态机工作流都需要人为干预,因此都有对应的接口程序以便于HandleExternalEvent活动进行绑定。

  接口代码:

    [ExternalDataExchange]  //using System.Workflow.Activities;
public interface IEvent
{
event EventHandler<ExternalDataEventArgs> Event1;
}

  创建一个状态机工作流项目,在工作流设计界面上添加两个"State"活动,并且将其分别命名为"提交申请"和"结束",然后通过右键菜单将它们分别设置为工作流的"启动"和"终止"状态。
在"提交申请"状态中添加EventDriven子活动,并且在该EventDriven活动中添加HandleExternalEvent子活动,然后与接口项目中定义的"Event1"事件进行绑定。

  完成后的工作流界面如下所示:

  

  

  

  状态机工作流的"起始"类型状态和"业务逻辑过程"类型的状态可以添加"StateInitialization","StateFinalization"子活动,"终止"类型的状态是不能添加这两个子活动的。

  在右键菜单中通过"添加 StateInitialization"和"添加 StateFinalization",又或者从工具栏中将子活动直接添加到"State"活动中,"StateInitialization"和"StateFinalization"子活动只是一个普通的容器类型活动,它们会在"State"活动开始和结束时分别被触发,这就可以起到类似于Window窗体"Load"事件和"FormClosed"事件的作用。

   

  更好地观察"StateInitialization"和"StateFinalization"子活动,和EventDriven子活动之间的运行顺序,可以向这两个子活动里面分别添加一个Code,然后绑定一个弹出窗口事件。工作流代码如下:

    public sealed partial class Workflow1 : StateMachineWorkflowActivity
{
public Workflow1()
{
InitializeComponent();
} private void Code1Execute(object sender, EventArgs e)
{
MessageBox.Show("StateInitialization开始执行!");
} private void Code2Execute(object sender, EventArgs e)
{
MessageBox.Show("StateFinalization开始执行!");
} private void handleExternalExecute(object sender, ExternalDataEventArgs e)
{
MessageBox.Show("handleExternalEvent开始执行!");
}
}

  创建一个WinForm程序,只有一个按钮,界面如下:

  

  Winform程序代码如下:

    public partial class Form1 : Form, ClassLibrary1.IEvent
{
public event EventHandler<ExternalDataEventArgs> Event1; public WorkflowRuntime workflowruntime;
private WorkflowInstance workflowinstance;
private ExternalDataExchangeService exterserv;
static AutoResetEvent waitHandle = new AutoResetEvent(false); public Form1()
{
InitializeComponent(); workflowruntime = new WorkflowRuntime();
exterserv = new ExternalDataExchangeService(); workflowruntime.AddService(exterserv);
exterserv.AddService(this); workflowruntime.StartRuntime(); Type wftype = typeof(WorkflowConsoleApplication1.Workflow1);
workflowinstance = workflowruntime.CreateWorkflow(wftype);
workflowinstance.Start();
} private void btn1_Click(object sender, EventArgs e)
{
Event1(null, new ExternalDataEventArgs(workflowinstance.InstanceId));
}
}

  弹出对话框顺序如下,启动程序,未点按钮:

  

  点击提交按钮后:

    

  • StateInitialization:在工作流启动时执行;
  • StateFinalization:在工作流完成时执行;

WWF3状态机工作流<WWF第七篇>的更多相关文章

  1. WWF3追踪功能<WWF第六篇>

    WWF工作流提供了Tracking跟踪功能来对工作流实例及其所包含的活动在运行时的状态进行跟踪,以便用户在需要时可以通过这些历史信息进行分析.WWF的Tracking跟踪功能是通过"SqlT ...

  2. 第七篇 Integration Services:中级工作流管理

    本篇文章是Integration Services系列的第七篇,详细内容请参考原文. 简介在上一篇文章,我们创建了一个新的SSIS包,学习了SSIS中的脚本任务和优先约束,并检查包的MaxConcur ...

  3. 第七篇 SQL Server代理作业活动监视器

    本篇文章是SQL Server代理系列的第七篇,详细内容请参考原文 在这一系列的上一篇,你创建并配置SQL Server代理作业.每个作业有一个或多个步骤,可能包含大量的工作流.在这篇文章中,将查看作 ...

  4. 【译】第七篇 Integration Services:中级工作流管理

    本篇文章是Integration Services系列的第七篇,详细内容请参考原文. 简介在上一篇文章,我们创建了一个新的SSIS包,学习了SSIS中的脚本任务和优先约束,并检查包的MaxConcur ...

  5. 【译】第七篇 SQL Server代理作业活动监视器

    本篇文章是SQL Server代理系列的第七篇,详细内容请参考原文 在这一系列的上一篇,你创建并配置SQL Server代理作业.每个作业有一个或多个步骤,可能包含大量的工作流.在这篇文章中,将查看作 ...

  6. Workflow笔记2——状态机工作流

    状态机工作流 在上一节Workflow笔记1——工作流介绍中,介绍的是流程图工作流,后来微软又推出了状态机工作流,它比流程图功能更加强大. 状态机工作流:就是将工作流系统中的所有的工作节点都可以看做成 ...

  7. SharePoint 2013 状态机工作流之扩展自定义状态

    当我们使用SharePoint 2013的状态机工作流时,发现一个非常不爽的事情,就是SharePoint 所有的工作流状态,都是固定的那些,没办法显示我们自定义的状态,后来经过Google发现,原来 ...

  8. SharePoint 2013 状态机工作流之日常报销示例

    简单介绍下状态机工作流,状态机工作流提供了一系列的状态.工作流从初始状态开始,到终止状态结束.两个状态之间定义行为进行过渡.通常情况下,状态机工作流对事件作出反应,事件的发生将会使状态发生改变. 1. ...

  9. 解剖SQLSERVER 第七篇 OrcaMDF 特性概述(译)

    解剖SQLSERVER 第七篇  OrcaMDF 特性概述(译) http://improve.dk/orcamdf-feature-recap/ 时间过得真快,这已经过了大概四个月了自从我最初介绍我 ...

随机推荐

  1. Apriori 关联算法学习

    1. 挖掘关联规则 1.1   什么是关联规则 一言蔽之,关联规则是形如X→Y的蕴涵式,表示通过X可以推导“得到”Y,其中X和Y分别称为关联规则的先导(antecedent或left-hand-sid ...

  2. HDU 5701 中位数计数

    这题真的很恶心,做了一天,最后问学长,才懂题意是什么,原来我一直都没读懂题.这我真的就无语了,你的题意多两句话会死啊?你测试样例多两个例子就不行啊?真蛋疼,题意都不懂,还做个shi? 题里说的是区间, ...

  3. HDU 1272 小希的迷宫(并查集)

    题解: 首先,init,find,union操作都是模版,多敲几遍,在记记,就没问题了. 然后,本题就是多了一个flag数组,记录数据是否出现过,最后记录最小,和最大,遍历一般他们的父亲,只有一个就是 ...

  4. Eclipse中构建Fluent风格到Formatter

    The place to set this is on the "Line Wrapping" tab of the code formatting preferences pag ...

  5. ubuntu网络配置相关知识(转载)

    From:http://os.51cto.com/art/201003/188055.htm 文章主要介绍Ubuntu网络配置,希望能让Linux新手学习参考.更好使用Ubuntu.更有效的学习Ubu ...

  6. jquery判断自己是父节点的第几个子节点

    <div> <span>内容</span> <span>内容</span> <span>内容</span> < ...

  7. java记录在线人数小案例

    文件目录: web.xml: <?xml version="1.0" encoding="UTF-8"?> <web-app version= ...

  8. delphi的tserversocket控件如何接收16进制数

    http://bbs.csdn.net/topics/390473005 对方客户端发送数据如:68 00 00··········:接收完成后,数据长度没错(13),但是显示接收结果时,只显示一个字 ...

  9. Apahce映射网络路径

    要点有两个: 1. 要使用全路径,不要使用映射的网络驱动器.2. 路径之间用斜杠/,不要用反斜杠\. Alias /weili.mobile "//vmware-host/Shared Fo ...

  10. poj 2253 Frogger dijkstra算法实现

    点击打开链接 Frogger Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 21653   Accepted: 7042 D ...