其实,以我的体会,工作流(Workflow Foundation)从它一诞生就褒贬不一。至少它确实目前看起来还是比较难用。在.NET 3.5以及之前的版本中,为了实现工作流,我们还是需要编写相当多的代码。

我觉得,WF给我们带来的主要有几点是值得了解的

1. 通过可视化的界面将流程设计与程序逻辑分离开来。

流程设计的可以只管流程,他们不要知道怎么做。流程设计的人员可能(或者一定)不会用Visual Studio,他们可以使用一些简单的设计器工具。例如下面的这个小例子就是一个独立的程序,上面包装了WF的设计器。结合自定义Activity的设计,可以将业务逻辑隐藏起来。

2.业务逻辑的数据还是需要我们自己设计数据库保存以及维护的

这是很多人疑惑的,他们觉得既然有Workflow Foundation,就万事大吉了。因为工作流实例确实也有数据,而且我们可以持久化将其保存起来嘛。

停!这不是一个正确的想法。工作流的持久化服务顾名思义,其实主要是为了给我们维护长时间工作的流程信息的(可以在空闲的时候卸载,保存到数据库等)。

大家应该这样理解,Workflow Foundation只是管流程的部分,它不管数据。

没错,它只管流程。这有什么问题么,它管好这个就够了,而且确实能帮很大的忙,不是吗?

这样,我们就可以将注意力放在业务数据的管理,而不是流程状态的管理之类。

3. 一般一套工作流的解决方案需要包含哪些组件

请注意上面选中的项目,我来解释一下

3.1 WorkflowLibrary 这个项目包含了工作流设计,它是可视化设计的成果。下图是一个典型的审批流程

3.2 OrderApprovalEventType 这个项目包含了工作流设计时可能会用到的一些接口和事件定义。为什么需要用事件呢?一般我们的流程如果需要等待用户干预,诸如审批之类的情况,就需要这样做,因为它可能不是立即发生的。

注意,接口要标记为ExternalDataExchange,事件参数需要继承ExternalDataEventArgs,而且必须可序列化

3.3 Contracts 这个项目是标准的WCF合约定义,因为我们是分了服务器和客户端的,他们之间通过WCF通讯,包括创建流程,以及激发事件等等

3.4 Services,这就是具体实现的WCF服务,在这里可以启动工作流运行时,并且按照客户端指令做相应的事情。这里的代码是相当多的。

using System;

using System.Collections.Generic;

using System.Linq;

using Contracts;

using System.ServiceModel;

using System.Workflow.Runtime;

using OrderApprovalEventType;

using System.Workflow.Activities;

using System.Workflow.Runtime.Hosting;

using System.Workflow.Runtime.Tracking;

namespace Services

{

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]//只有一个实例

public class OrderService:IOrderService

{

//运行时

private WorkflowRuntime runtime = null;

//所有实例

private List instances = new List();

//本地服务

LocalService local = null;

public OrderService() {

runtime = new WorkflowRuntime();

//添加数据交换服务,可以激发事件

ExternalDataExchangeService svr = new ExternalDataExchangeService();

runtime.AddService(svr);

local = new LocalService();

svr.AddService(local);

//添加持久化服务,保存实例

//F:\Windows\Microsoft.NET\Framework\v3.0\Windows Workflow Foundation\SQL\zh-CHS这里会有脚本

var db = "server=(local);database=WorkflowFoundation;integrated security=true";

SqlWorkflowPersistenceService sqlsvc = new SqlWorkflowPersistenceService(db);

runtime.AddService(sqlsvc);

//添加跟踪服务,可以对服务进行诊断和调试

SqlTrackingService tracksvc = new SqlTrackingService(db);

runtime.AddService(tracksvc);

//绑定有关的事件

runtime.WorkflowStarted += new EventHandler(runtime_WorkflowStarted);

runtime.WorkflowCompleted += new EventHandler(runtime_WorkflowCompleted);

runtime.WorkflowCreated += new EventHandler(runtime_WorkflowCreated);

runtime.WorkflowAborted += new EventHandler(runtime_WorkflowAborted);

runtime.WorkflowTerminated += new EventHandler(runtime_WorkflowTerminated);

runtime.WorkflowUnloaded += new EventHandler(runtime_WorkflowUnloaded);

runtime.StartRuntime();//启动运行时

Console.WriteLine("工作流服务器已经准备就绪");

//加载那些保存好的流程实例

foreach (var item in sqlsvc.GetAllWorkflows())

{

var instance =(WorkflowLibrary.Workflow1)runtime.GetWorkflow(item.WorkflowInstanceId).GetWorkflowDefinition();

instances.Add(

new WorkflowIntanceData()

{

Id = item.WorkflowInstanceId,

Amount = instance.Amount

});

}

}

void runtime_WorkflowUnloaded(object sender, WorkflowEventArgs e)

{

Console.WriteLine("时间:{0},卸载流程:{1}", DateTime.Now, e.WorkflowInstance.InstanceId);

}

void runtime_WorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)

{

Console.WriteLine("时间:{0},终止流程:{1}", DateTime.Now, e.WorkflowInstance.InstanceId);

}

void runtime_WorkflowAborted(object sender, WorkflowEventArgs e)

{

Console.WriteLine("时间:{0},中断流程:{1}", DateTime.Now, e.WorkflowInstance.InstanceId);

}

void runtime_WorkflowCreated(object sender, WorkflowEventArgs e)

{

Console.WriteLine("时间:{0},创建流程:{1}", DateTime.Now, e.WorkflowInstance.InstanceId);

}

void runtime_WorkflowCompleted(object sender, WorkflowCompletedEventArgs e)

{

var found = instances.FirstOrDefault(d => d.Id == e.WorkflowInstance.InstanceId);

if (found != null)

instances.Remove(found);

Console.WriteLine("时间:{0},完成流程:{1}", DateTime.Now, e.WorkflowInstance.InstanceId);

}

void runtime_WorkflowStarted(object sender, WorkflowEventArgs e)

{

Console.WriteLine("时间:{0},启动流程:{1}", DateTime.Now, e.WorkflowInstance.InstanceId);

}

#region IOrderService 成员

public void StartRequest(Guid id, int amount)

{

//准备数据

var initParam =new Dictionary();

initParam.Add("Amount",amount);

//创建实例

var instance = runtime.CreateWorkflow(

typeof(WorkflowLibrary.Workflow1),

initParam,

id);

//保存有关数据

instances.Add(

new WorkflowIntanceData(){

Id = id,

Amount = amount,

RequestEmployee="陈希章"

});

//启动实例

instance.Start();

}

public void ProcessRequest(Guid id, OrderApprovalEventType.ProcessResult result, string notes)

{

var args = new ProcessEventArgs(id);

args.Result = result;

args.Notes = notes;

//从集合中删除掉有关的实例

var found = instances.FirstOrDefault(d => d.Id == id);

if (found != null)

instances.Remove(found);

local.RaiseEvent(args);//激发事件

}

public List GetWorkflowInstances()

{

return instances.Where(d => d.Amount >= 2000).ToList();

}

#endregion

#region IOrderService 成员

public void UnLoad(Guid id)

{

runtime.GetWorkflow(id).Unload();//要求开启MSDTC服务

}

#endregion

~OrderService() {

//析构的时候将所有未完成的工作流实例保存起来

foreach (var item in runtime.GetLoadedWorkflows())

{

item.Unload();

}

}

public void UnloadAllInstances() {

foreach (var item in runtime.GetLoadedWorkflows())

{

item.Unload();

}

}

}

[Serializable]//这个必须标记为可序列化

internal class LocalService : ManagerEvent

{

#region ManagerEvent 成员

public event EventHandler Process;

#endregion

internal void RaiseEvent(ProcessEventArgs e) {

//这里可能要更新数据库

if (Process != null)

Process(this, e);

}

}

}

注意:这里有一个所谓本地服务的概念,是要实现第二步的那个接口,并编写有关触发事件的代码

3.5 HostService 如上都准备好之后,接下来就是通过一定的方式托管这些服务了。我们可以采用Windows Service来托管

3.6 SimpleClient 最后当然少不了要有客户端界面来实现一些操作。我们这里使用了Windows Forms作为界面。

using System;

using System.Windows.Forms;

using System.ServiceModel;

using Contracts;

namespace SimpleClient

{

public partial class Form1 : Form

{

IOrderService proxy = null;

public Form1()

{

InitializeComponent();

}

protected override void OnLoad(EventArgs e)

{

base.OnLoad(e);

ChannelFactory factory = new ChannelFactory(new BasicHttpBinding(), new EndpointAddress("http://localhost:8080/OrderService"));

proxy = factory.CreateChannel();

}

private void btRequest_Click(object sender, EventArgs e)

{

int amount = int.Parse(txtAmount.Text);

proxy.StartRequest(Guid.NewGuid(), amount);

MessageBox.Show("已经发起了一个订单");

}

private void btGet_Click(object sender, EventArgs e)

{

dgvRequests.DataSource = proxy.GetWorkflowInstances();

}

private void dgvRequests_CellEnter(object sender, DataGridViewCellEventArgs e)

{

btOK.Enabled = btCancel.Enabled = true;

}

private void dgvRequests_CellLeave(object sender, DataGridViewCellEventArgs e)

{

//btOK.Enabled = btCancel.Enabled = false;

}

private void btOK_Click(object sender, EventArgs e)

{

var row = dgvRequests.Rows[dgvRequests.SelectedCells[0].RowIndex];

var id = (Guid)row.Cells[0].Value;

proxy.ProcessRequest(

id, OrderApprovalEventType.ProcessResult.Approval, txtNotes.Text);

}

private void btCancel_Click(object sender, EventArgs e)

{

var row = dgvRequests.Rows[dgvRequests.SelectedCells[0].RowIndex];

var id = (Guid)row.Cells[0].Value;

proxy.ProcessRequest(

id, OrderApprovalEventType.ProcessResult.Reject, txtNotes.Text);

}

private void btUnload_Click(object sender, EventArgs e)

{

var row = dgvRequests.Rows[dgvRequests.SelectedCells[0].RowIndex];

var id = (Guid)row.Cells[0].Value;

proxy.UnLoad(id);

}

}

}

这样,一套工作流解决方案就做好了。这个架构可以供很多朋友参考

另外,下面有几篇有关的文章可以参考学习

工作流内部工作原理(一)

工作流内部工作原理(二)

工作流内部工作原理(三)

java中workFlowEvent_关于工作流(Workflow Foundation)的一些总结归纳相关推荐

  1. java中workFlowEvent_关于WorkFlow的使用以及例子

    近期做项目,项目需要用到工作流方面的技术,我在这里与大家分享一个workFlow学习的地址,共大家学习. 各文档的说明: F资料 ├─Activity │  │  1_Activity 类.doc │ ...

  2. java中workFlowEvent_防止线程在java中重复处理

    问题陈述 我有一个JMS监听器作为一个线程来监听一个主题.一旦消息进入,我就会生成一个新的Thread来处理有界消息.因此,对于每个传入的消息,我产生一个新的线程. 我有一个场景,当重复消息按顺序注入 ...

  3. Windows workflow foundation入门

    Microsoft Windows Workflow Foundation (WWF) 是一个可扩展框架,用于在 Windows 平台上开发工作流解决方案.作为即将问世的 Microsoft WinF ...

  4. workflow java_workflow java实现的activity工作流实例 Develop 238万源代码下载- www.pudn.com...

    文件名称: workflow下载 收藏√  [ 5  4  3  2  1 ] 开发工具: Java 文件大小: 134 KB 上传时间: 2014-09-18 下载次数: 3 提 供 者: 张华 详 ...

  5. Windows Workflow Foundation之旅(六)——框架组成、工作流创作模式

    Windows Workflow Foundation之旅(六)--框架组成<?xml:namespace prefix = o ns = "urn:schemas-microsoft ...

  6. java workflow jbpm_工作流(workflow)定义和jBPM

    工作流(workflow)定义 工作流(Workflow)就是工作流程的计算模型,即将工作流程中的工作如何前后组织在一起的逻辑和规则在计算机中以恰当的模型进行表示并对其实施计算.根据 WfMC 的定义 ...

  7. 和我一起学Windows Workflow Foundation(1)-----创建和调试一个WF实例(转)

    和我一起学Windows Workflow Foundation(1)-----创建和调试一个WF实例 今天开始,我打算开始学习WWF,从网上搜索到了部分相关资料,也找到了一些文档和实验.但是,资料以 ...

  8. 微软Workflow Foundation 高阶透视

    什么是工作流?工作流是一组同软件或人交互的活动,以及活动间的联系,可以像一个流程图,也可以像一个状态机. [图一,左边是流程图,右边是状态机] 什么是微软Workflow Foundation?微软W ...

  9. Microsoft Windows Workflow Foundation 入门:开发人员演练

    有关向 Windows 平台添加工作流支持的初步知识 Microsoft Windows Workflow Foundation (WWF) 是一个可扩展框架,用于在 Windows 平台上开发工作流 ...

最新文章

  1. 客户端与服务器的数据交互
  2. 常考数据结构与算法:两个链表生成相加链表
  3. My97DatePicker日历插件
  4. Centos 7.4 安装ipython和mysql-python遇到的问题
  5. java.lang.OutOfMemoryError​异常解决方法
  6. 记一个鼠标略过时候的css动画
  7. 为什么接口需要加密传输
  8. workbeach约束简称_AnsysWorkbenchFluidFlow(FLUENT)经典问题.docx
  9. 矩阵分解 java_使用矩阵分解为推荐系统
  10. insert插入语句设置主键id回滚
  11. JAVA 搭建基于SPRINGBOOT的SSM(SPRING + SPRINGMVC + MYBATIS)的MAVEN项目
  12. 一个实用的String实现类(C++)
  13. 将数据追加到html 表格中,【HTML】使用Jquery实现将输入数据添加至表格中
  14. AntennaHome Launch 5G Combo Internal PCB Antenna /5G 全频 PCB天线
  15. 你不知道的“虚假需求”
  16. 老中医化妆品效果怎么样?舒缓系列拒绝敏感肌肤困扰
  17. mysql password_expired
  18. 【揭秘】CSDN博客上,超过百万访问量的Android牛人都是谁?
  19. python中content什么意思_python – 解析html时为什么我需要item.text和item.text_content()其他...
  20. http简介以及常见知识和http请求头,响应头,状态码,内容类型对照表分享(超实用)

热门文章

  1. 管理软件包
  2. linux jdk8下载
  3. 后知后觉者的学习方法
  4. 借助redis实现分布式定时任务锁
  5. 虚拟机桥接模式无法联网
  6. 解决input事件监听拼音输入法导致高频事件
  7. 显示器点距 测试软件,液晶显示器常见、尺寸、分辨率、点距
  8. GPO 管理员: 简单恢复GPO更改
  9. to string在C语言中,C++中的to_string()函数[C++11支持],to_string11
  10. mysql查询工资大于某个员工_一个SQL实现薪水大于所在部门平均薪水的员工