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

一、状态机工作流范例

  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. PL/SQL中批量执行SQL脚本(不可把所有的语句都复制到New SQL Windows)

    PL/SQL中批量执行SQL脚本,不可把所有的语句都复制到New SQL Window,因为这样会导致缓冲区过大而进程卡死! 最好的办法是将要执行的SQL脚本存放到指定文件中,如C:\insert.s ...

  2. Spark读写Hbase中的数据

    def main(args: Array[String]) { val sparkConf = new SparkConf().setMaster("local").setAppN ...

  3. DBA_Oracle Erp重启Database/Application/Concurrent/Apache(案例)

    2014-12-27 Created By BaoXinjian

  4. linux 标准输入输出

    文件描述符是一个简单的正整数,用以标明每一个被进程所打开的文件和socket.最前面的三个文件描述符(0,1,2)分别与标准输入(stdin),标准输出(stdout)和标准错误(stderr)对应 ...

  5. mysql 批量插入

    对于批量插入: 1.在建立唯一索引的情况下,,从前往后,如果遇到索引重复错误 则停止插入(前面的插入成功),错误后面的即使正确也不会插入 方法1:insert igore 后 解决此问题 (ignor ...

  6. [物理学与PDEs]书中出现的符号及其意义汇总

    1. 标量 $\ve_0$: $=8.85419\times 10^{-2}C^2/(N\cdot m^2)$ 真空中的介电常数 $\ve$: 介电常数 $\ve_r$: $=1+\chi_e$ 相对 ...

  7. db2删除数据库

    1.断开所有连接  db2 stop application all   force 2.停止数据库    db2stop 3.删除数据库(系统管理员权限下)db2 drop  数据库name

  8. vim使用快捷键

    vim使用快捷键 索引 1. 关于Vim 1.1 Vim的几种模式 2. 启动Vim 3. 文档操作 4. 光标的移动 4.1 基本移动 4.2 翻屏 4.3 标记 5. 插入文本 5.1 基本插入 ...

  9. firebug下载时出现there was an error loading firebug

    打开Firefox -> Preferences -> Advance ->Certificates 将Query OSCP....前面的checkbox取消

  10. 用jQuery之后,之前javascript的一些方法就不能用了吗

    用jQuery之后,之前javascript的一些方法就不能用了吗? 比如$("#btn").onclick = function(){}这种用法?或者$("#btn&q ...