WWF3状态机工作流<WWF第七篇>
状态机是另外一种常见的工作流类型。它是以状态的变迁为驱动而进行业务流转的,是一定需要人为干预的,而不像顺序类型工作流那样可以按照事先设计好的业务流程一步一步依次执行下去。
一、状态机工作流范例
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第七篇>的更多相关文章
- WWF3追踪功能<WWF第六篇>
WWF工作流提供了Tracking跟踪功能来对工作流实例及其所包含的活动在运行时的状态进行跟踪,以便用户在需要时可以通过这些历史信息进行分析.WWF的Tracking跟踪功能是通过"SqlT ...
- 第七篇 Integration Services:中级工作流管理
本篇文章是Integration Services系列的第七篇,详细内容请参考原文. 简介在上一篇文章,我们创建了一个新的SSIS包,学习了SSIS中的脚本任务和优先约束,并检查包的MaxConcur ...
- 第七篇 SQL Server代理作业活动监视器
本篇文章是SQL Server代理系列的第七篇,详细内容请参考原文 在这一系列的上一篇,你创建并配置SQL Server代理作业.每个作业有一个或多个步骤,可能包含大量的工作流.在这篇文章中,将查看作 ...
- 【译】第七篇 Integration Services:中级工作流管理
本篇文章是Integration Services系列的第七篇,详细内容请参考原文. 简介在上一篇文章,我们创建了一个新的SSIS包,学习了SSIS中的脚本任务和优先约束,并检查包的MaxConcur ...
- 【译】第七篇 SQL Server代理作业活动监视器
本篇文章是SQL Server代理系列的第七篇,详细内容请参考原文 在这一系列的上一篇,你创建并配置SQL Server代理作业.每个作业有一个或多个步骤,可能包含大量的工作流.在这篇文章中,将查看作 ...
- Workflow笔记2——状态机工作流
状态机工作流 在上一节Workflow笔记1——工作流介绍中,介绍的是流程图工作流,后来微软又推出了状态机工作流,它比流程图功能更加强大. 状态机工作流:就是将工作流系统中的所有的工作节点都可以看做成 ...
- SharePoint 2013 状态机工作流之扩展自定义状态
当我们使用SharePoint 2013的状态机工作流时,发现一个非常不爽的事情,就是SharePoint 所有的工作流状态,都是固定的那些,没办法显示我们自定义的状态,后来经过Google发现,原来 ...
- SharePoint 2013 状态机工作流之日常报销示例
简单介绍下状态机工作流,状态机工作流提供了一系列的状态.工作流从初始状态开始,到终止状态结束.两个状态之间定义行为进行过渡.通常情况下,状态机工作流对事件作出反应,事件的发生将会使状态发生改变. 1. ...
- 解剖SQLSERVER 第七篇 OrcaMDF 特性概述(译)
解剖SQLSERVER 第七篇 OrcaMDF 特性概述(译) http://improve.dk/orcamdf-feature-recap/ 时间过得真快,这已经过了大概四个月了自从我最初介绍我 ...
随机推荐
- Shuffle相关分析
Shuffle描述是一个过程,表现出的是多对多的依赖关系.Shuffle是连接map阶段和Reduce阶段的纽带,每个Reduce Task都会从Map Task产生的数据里读取其中的一片数据.Shu ...
- [实变函数]5.6 Lebesgue 积分的几何意义 $\bullet$ Fubini 定理
1 本节推广数学分析中的 Fubini 定理. 为此, 先引入 (1)(从低到高) 对 $A\subset \bbR^p, B\subset\bbR^q$, $$\bex A\times B=\sed ...
- UCOS-信号标志组(学习笔记)
信号标志组即根据各任务的信号进行逻辑运算,根据逻辑运算的结果决定是否进行.发送方指定向那个标志组的哪一位(响应位等于1表明向哪一位发)发1还是0.等待逻辑结果的任务指定等待那个标志组的哪几位.这几位按 ...
- Laravel 部署安装到虚拟主机的方法(折腾了一周,终于成功部署,原来是虚拟机不加载.env,谢谢莫回首http://lxl520.com/index.php/archives/88/!)
作者:莫回首链接:https://www.zhihu.com/question/35497879/answer/111241182来源:知乎著作权归作者所有,转载请联系作者获得授权. 序 lara ...
- 按钮/文本框 disabled
需求:已登入的,将用户的信息回填,用户文本框内容不能更改. 按钮: <button type="button" id="btnSearch">< ...
- ios模拟器未能安装此应用程序
网上介绍了很多方法,觉得有些不太靠谱.这里只解释我试验过的最简单最粗暴的方法: 删除模拟器上旧的APP 以外,也可以做 CLEAN (cmd+shift+K) 把旧的build 删掉.
- 织梦DEDECMS文章、栏目页获取当前页面顶级栏目名称的方法
在用织梦做一些项目时,时常会碰到需要在当前页面调用顶级栏目名称的时候,织梦默认{dede:field name='typename' /} 可以获取当前栏目页上一级栏目的名称,而不是当前栏目顶级栏目名 ...
- MYSQL C API : mysql_real_connect()
MYSQL * mysql_real_connect( MYSQL *mysql, const char *host, const char *user, const char *passwd, co ...
- crm 2011 plugin setparent setbusiness 用户更改经理 更改办事处
背景: 在更改经理或者更改办事处时,使用plugin处理相应的团队. 问题:plugin写完,注册时发现使用update注册没有效果,然后bing得到,这里要使用setbusiness 和 setpa ...
- Delphi 中 paramstr 的用法及参数意义
原型 function paramstr(i:index):string 对于任何application paramstr(0)都默认代表的是应用程序的绝对路径.那 ...