WWF提供的持续化功能会自动记录工作流实例以及它包含的所有活动的执行状态,这些状态并不是指工作流上流转的表单所呈现的业务逻辑状态。WWF持续化功能就是将未执行完成的工作流实例以及该实例中各种活动的状态,以文件或数据库方式进行存储,待需要的时候再重新将其加载回工作流运行时容器Runtime中。运行完毕才删除。

  在具体操作中通过"SqlWorkflowPersistenceService"类来实现持续化的功能,基于数据库,其他数据库需重新实现接口。

一、创建SqlPersistenceService数据库

  要在SQLServer实现工作流的保存、恢复功能,需要创建一些相关表与存储过程。默认情况下在C:\Windows\Microsoft.NET\Framework\v3.5\SQL\EN 路径下有SqlPersistenceProviderSchema.sql和SqlPersistenceProviderLogic.sql两个文件,打开SQLServer创建一个名叫SqlPersistenceService的数据库,按顺序执行以上两个sql脚本。此时,SqlPersistenceService数据库就创建了几个表与存储过程。

  如果实在不行,就把SqlPersistenceService数据库附加进来。http://files.cnblogs.com/kissdodog/WWF%E6%8C%81%E7%BB%AD%E5%8C%96%E6%95%B0%E6%8D%AE%E5%BA%93.rar

  接口如下:

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

  新建一个工作流如下:

  

  里面是3个HandleExternalEvent活动,分别于刚刚定义的接口事件相绑定。

  

  在bin目录里面添加一个XML文件,其代码如下:

<WorkflowInstances />

  新建一个Winform程序,界面如下:

  

  代码如下:

    public partial class Form1 : Form, ClassLibrary1.IEvent
{
//创建一个WinForm引用程序,然后继承并实现接口中定义的事件
public event EventHandler<ExternalDataEventArgs> PMApproved;
public event EventHandler<ExternalDataEventArgs> VPApproved;
public event EventHandler<ExternalDataEventArgs> StaffSubmit; private WorkflowRuntime runtime;
//SQLServer中的"SqlPersistenceService"数据库是用来存储工作流实例及其活动的运行状态。
//业务逻辑状态也能够以XML文件形式进行存储,当程序刚运行无流程在运行时,添加一个空xml文件
//名为:workflowInstances.xml直接放在bin目录
const string instanceFilename = "workflowInstances.xml"; WorkflowInstance instance; public Form1()
{
InitializeComponent(); this.runtime = new WorkflowRuntime(); runtime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(runtime_WorkflowCompleted);
runtime.WorkflowIdled += OnWorkflowIdled; //应用程序启动时以"SqlWorkflowPersistenceService"为对象来实例化"WorkflowPersistenceService"类,
//并通过"SqlWorkflowPersistenceService"来连接SQLServer数据库,同时将工作流的持续化服务加载到工作流运行时容器Runtime中。
WorkflowPersistenceService persistenceService =
new SqlWorkflowPersistenceService(
"server=CZZ;database=SqlPersistenceService;uid=sa;pwd=123");
runtime.AddService(persistenceService); ExternalDataExchangeService dataService = new ExternalDataExchangeService();
runtime.AddService(dataService); dataService.AddService(this); LoadWorkflowData(); runtime.StartRuntime(); }
//在工作流空闲状态时并将其从内存中卸载出去
//重载工作流的"WorkflowIdled"事件,当工作流处于等待状态下时将通过该事件来调用工作流实例的"TryUnload()"方法,
//使它激发工作流的"WorkflowPersisted"事件,这样工作流就可以通过"WorkflowPersistenceService"服务将信息自动保存到SQL Server数据库,以实现持续化功能。
static void OnWorkflowIdled(object sender, WorkflowEventArgs e)
{
e.WorkflowInstance.TryUnload();
} //当工作流完成后,将界面列表中的相应数据删除
//当工作流运行结束时还需要对界面列表中的相关信息进行删除,用户可以通过重载工作流的"WorkflowCompleted"事件来实现。
//要注意分清楚,事件是工作流的事件,而删除界面是WinForm程序的事。工作流与应用程序不在同一个线程,因此不能直接调用。这种情况可以通过委托来实现。
void runtime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)
{
RemoveListViewItem remove = new RemoveListViewItem(RemoveListViewItemAsync);
Invoke(remove, e.WorkflowInstance.InstanceId);
}
private delegate void RemoveListViewItem(Guid instanceId);
private void RemoveListViewItemAsync(Guid instanceId)
{
foreach (ListViewItem item in ListViewExisting.Items)
{
if (item.SubItems[].Text.Equals(instanceId.ToString()))
ListViewExisting.Items.Remove(item);
}
} //用户提交请假单的按钮事件
private void btnSubmit_Click(object sender, EventArgs e)
{
instance = runtime.CreateWorkflow(typeof(WorkflowConsoleApplication1.Workflow1));
instance.Start(); StaffSubmit(null, new ExternalDataEventArgs(instance.InstanceId)); ListViewExisting.Items.Add(new ListViewItem(new String[] { instance.InstanceId.ToString(), this.txtDay.Text, "提交请假单" })); }
//当窗体关闭时,将列表中请假单的信息保存到XML中
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
SaveWorkflowData();
runtime.Dispose();
}
//项目经理审批的按钮
private void btnPMArrpoved_Click(object sender, EventArgs e)
{
instance = runtime.GetWorkflow(new Guid(ListViewExisting.SelectedItems[].Text)); PMApproved(null, new ExternalDataEventArgs(instance.InstanceId)); foreach (ListViewItem item in ListViewExisting.Items)
{
if (item.SubItems[].Text.Equals(instance.InstanceId.ToString()))
item.SubItems[].Text = "等待VP审批";
}
}
//副总经理审批的按钮
private void btnVPApproved_Click(object sender, EventArgs e)
{
instance = runtime.GetWorkflow(new Guid(ListViewExisting.SelectedItems[].Text));
VPApproved(null, new ExternalDataEventArgs(instance.InstanceId));
foreach (ListViewItem item in ListViewExisting.Items)
{
if (item.SubItems[].Text.Equals(instance.InstanceId.ToString()))
item.SubItems[].Text = "审批通过";
}
}
#region 读写XML的方法
/// <summary>
/// 从XML文件中读取已经钝化的工作流实例的信息
/// </summary>
public void LoadWorkflowData()
{
XmlTextReader reader = new XmlTextReader(instanceFilename);
try
{
while (reader.Read())
{
if (reader.Name.Equals("WorkflowInstance"))
{
ListViewExisting.Items.Add(
new ListViewItem(
new String[] { reader.GetAttribute("InstanceId"),
reader.GetAttribute("Day"),
reader.GetAttribute("State")}));
}
}
reader.Close();
}
catch (FileNotFoundException) { }
}
/// <summary>
/// 保存工作流实例的信息到XML文件中
/// </summary>
public void SaveWorkflowData()
{
XmlTextWriter writer = new XmlTextWriter(instanceFilename, Encoding.Unicode);
writer.WriteStartElement("WorkflowInstances");
foreach (ListViewItem item in ListViewExisting.Items)
{
writer.WriteStartElement("WorkflowInstance");
writer.WriteAttributeString("InstanceId", item.SubItems[].Text);
writer.WriteAttributeString("Day", item.SubItems[].Text);
writer.WriteAttributeString("State", item.SubItems[].Text);
writer.WriteEndElement();
}
writer.WriteEndElement();
writer.Flush();
writer.Close();
}
#endregion
}

  执行效果如下:

  

  由于在关闭窗口的时候,会将当前工作流的执行状态保存到XML文件和数据库中,而下次打开的时候,回去读取上次执行到的状态,所以当工作流执行到某一步关闭窗口再打开,会显示上次保存的状态。

WWF3的持续化<第五篇>的更多相关文章

  1. 【Python五篇慢慢弹(4)】模块异常谈python

    模块异常谈python 作者:白宁超 2016年10月10日12:08:31 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给出的pythondo ...

  2. 前端工程师技能之photoshop巧用系列第五篇——雪碧图

    × 目录 [1]定义 [2]应用场景 [3]合并[4]实现[5]维护 前面的话 前面已经介绍过,描述性图片最终要合并为雪碧图.本文是photoshop巧用系列第五篇——雪碧图 定义 css雪碧图(sp ...

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

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

  4. ElasticSearch入门 第五篇:使用C#查询文档

    这是ElasticSearch 2.4 版本系列的第五篇: ElasticSearch入门 第一篇:Windows下安装ElasticSearch ElasticSearch入门 第二篇:集群配置 E ...

  5. 持续化集成Jenkins的系统配置

    最近在研究selenium2自动化测试,用到持续化集成jenkins.由于之前仅限于使用,而没有真正动手配置过,所以现在学习从零开始,搭建持续化集成,故而有了这篇博客. 先介绍一下项目持续集成测试,这 ...

  6. mysql第五篇 : MySQL 之 视图、触发器、存储过程、函数、事物与数据库锁

    第五篇 : MySQL 之 视图.触发器.存储过程.函数.事物与数据库锁 一.视图 视图是一个虚拟表(非真实存在的),其本质是‘根据SQL语句获取动态的数据集,并为其命名‘ ,用户使用时只需使用“名称 ...

  7. 【Python五篇慢慢弹】快速上手学python

    快速上手学python 作者:白宁超 2016年10月4日19:59:39 摘要:python语言俨然不算新技术,七八年前甚至更早已有很多人研习,只是没有现在流行罢了.之所以当下如此盛行,我想肯定是多 ...

  8. 【Python五篇慢慢弹】数据结构看python

    数据结构看python 作者:白宁超 2016年10月9日14:04:47 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给出的pythondoc ...

  9. 【Python五篇慢慢弹(3)】函数修行知python

    函数修行知python 作者:白宁超 2016年10月9日21:51:52 摘要:继<快速上手学python>一文之后,笔者又将python官方文档认真学习下.官方给出的pythondoc ...

随机推荐

  1. ThreadPoolExecutor使用介绍

    private static ExecutorService exec = new ThreadPoolExecutor(8, 8, 0L,TimeUnit.MILLISECONDS, new Lin ...

  2. [UEditor]百度编辑器配置总结

    前端配置文件ueditor.config.js 前端有两个重要的配置属性: UEDITOR_HOME_URL: 配置百度编辑器的资源目录路径,你可以手动指定此路径,默认是有URL变量指定,而URL变量 ...

  3. [实变函数]2.1 度量空间 (metric space), $n$ 维 Euclidean 空间

    1 回忆:    $$\bex    \lim_{n\to\infty}a_n=a\lra \forall\ \ve>0,\ \exists\ N,\ \forall\ n\geq N,\mbo ...

  4. Java 内存泄露

    一.Java内存回收机制 不论哪种语言的内存分配方式,都需要返回所分配内存的真实地址,也就是返回一个指针到内存块的首地址.Java中对象是采用new或者反射的方法创建的,这些对象的创建都是在堆(Hea ...

  5. jquery 源码剖析1

    ()();   闭包,让声明的变量变成局部变量,使外部无法访问,防止和其他代码冲突,互不影响. (function(){ })();              和一般执行方法一样的. jQuery=f ...

  6. div高度自适应

    第一种: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3 ...

  7. 查看linux的版本

    1. uname -a ~$ uname -a Linux lubuntu-Vostro-A840 3.19.0-73-generic #81-Ubuntu SMP Tue Oct 18 16:02: ...

  8. 织梦后台更新,报错DedeCMS Error:Tag disabled:"php" more...

    网站采用织梦v5.7版本,在做过一次后台补丁更新后,再对网站“生成”操作的时候,无厘头出现报错“ 网站后台--系统--系统基本参数---其他选项 ---模板引擎禁用标签:php  ,把php删掉 保存 ...

  9. Mac添加环境变量的三种方法

    法一: sudo vi /etc/paths 来编辑 paths,将环境变量添加到 paths 中. vim 是一个编辑器,另外还有几个,如:Pico,Emacs. Hint:输入环境变量时,不用一个 ...

  10. maven项目导入报错

    极大可能是仓库设置问题