当前位置: 首页 > news >正文

一步一步学WF系列(一)——Hello world开始

. 什么是工作流

我给工作流下了这样的定义,工作流就是一个过程,这个过程会产生一定的结果。

其实,在OA系统中,审批流就是我们最常见的工作流之一。

另外,简单了说,其实我们所画的流程图就是一种最简单的工作流,工作流最大的特点就是图形化。工作流是按照顺序驱动或者事件驱动去触发下一步操作,从而最终得到一个结果。

其实,我们也可以把他理解为一个过程化的职责链。

2. 工作流的类型

工作流大致分为两类,顺序工作流和事件驱动工作流。

顺序工作流是我们很常见的工作流,这个工作流是由我们事先规定好的顺序一步步地走下去,他们执行的步骤是不可以改变的。

事件驱动工作流,我们也称之为有限状态机,他状态的变更是犹由于特定的事件而触发的。

举例如下:

顺序工作流:审批流其实就是典型的顺序工作流,一个审批对象一步步地层层审批,拿一次面试过程来说,首先人事部简历筛选,然后是技术经理面试,然后是总经理面试,这都是按照流程来的。

​编辑

事件驱动工作流:想想我们的软件工程流程,是不是这样的:

​编辑

3. 第一个实例:Hello world

学任何程序,第一个例子往往都是Hello world,这次也不例外。

让我们先来构建一个简单的WF小程序。

我所使用的环境是Visual Studio 2008 + .NET Framework 3.5 sp1来搭建项目:

首先让我们来熟悉环境:

打开VS2008,选择新建——> 项目:

​编辑

然后选择Workflow——>顺序工作流控制台应用程序。然后点击确定就进入了我们的WF项目中。

​编辑

在项目中,我们可以看到Program.cs和Workflow1.cs。Workflow1我不多说,这个当然是我们的工作流程序。

那来看一下Program.cs:

4. 宿主

Windows workflow foundation不是一个独立的产品,他需要在一个宿主的环境下才能运行。

这个宿主可以是控制台应用程序,Winform程序,也可以是ASP.NET程序。

WF的运行是通过工作流的运行时引擎来实现的。实际上,工作流运行时引擎和宿主的应用程序在同一进程中。

5. 继续Hello world

在工具箱中,拖出一个Code控件。

​编辑

然后为codeActivity1起一个有意义的Name为codeActivityHello。

然后去实现ExcuteCode事件,实现这个事件,运行库将自动调用这个方法。

实现如下:

<span style="color:#555555"><span style="background-color:#ffffff"><span style="color:#0000ff">private void </span>codeActivityHello_ExecuteCode(<span style="color:#0000ff">object </span>sender, <span style="color:#2b91af">EventArgs </span>e) { <span style="color:#2b91af">Console</span>.WriteLine(<span style="color:#a31515">"Hello world"</span>); }</span></span>

好了,让我们运行这段程序:

​编辑

6. 深入解析宿主文件

让我们进一步地去解析宿主文件Program.cs:

<span style="color:#555555"><span style="background-color:#ffffff"><span style="color:#0000ff">static void </span>Main(<span style="color:#0000ff">string</span>[] args) { <span style="color:#0000ff">using</span>(<span style="color:#2b91af">WorkflowRuntime </span>workflowRuntime = <span style="color:#0000ff">new </span><span style="color:#2b91af">WorkflowRuntime</span>()) { <span style="color:#2b91af">AutoResetEvent </span>waitHandle = <span style="color:#0000ff">new </span><span style="color:#2b91af">AutoResetEvent</span>(<span style="color:#0000ff">false</span>); workflowRuntime.WorkflowCompleted += <span style="color:#0000ff">delegate</span>(<span style="color:#0000ff">object </span>sender, <span style="color:#2b91af">WorkflowCompletedEventArgs </span>e) {waitHandle.Set();}; workflowRuntime.WorkflowTerminated += <span style="color:#0000ff">delegate</span>(<span style="color:#0000ff">object </span>sender, <span style="color:#2b91af">WorkflowTerminatedEventArgs </span>e) { <span style="color:#2b91af">Console</span>.WriteLine(e.Exception.Message); waitHandle.Set(); }; <span style="color:#2b91af">WorkflowInstance </span>instance = workflowRuntime.CreateWorkflow(<span style="color:#0000ff">typeof</span>(WorkflowConsoleApplication3.<span style="color:#2b91af">Workflow1</span>)); instance.Start(); waitHandle.WaitOne(); } }</span></span>

WorkflowRuntime:为工作流执行引擎提供了可执行环境。

接下来,workflowRuntime.WorkflowCompleted事件和workflowRuntimeTerminated分别指定了工作流执行结束和执行终止时所调用的匿名方法。

接下来创造一个相应的工作流的实例,然后让这个实例开始执行。

而后去调用AutoResetEvent的实例waitHandle.WaitOne()作用在于阻止当前线程的执行,从而让该工作流进行结束后,即WorkflowRuntime.WorkflowComplete事件技术后,我们再可以在这条语句后来调用执行其他的语句。

没什么好说的了,接下来去创建一个工作流的实例,然后开始执行。

7. 让程序更有趣一些

分析过宿主文件之后,那我们开始让程序更有趣一些。

而手脚就让我们从那两个匿名方法开始。

首先修改workflow1.cs 的 后台代码:

<span style="color:#555555"><span style="background-color:#ffffff"><span style="color:#0000ff">public sealed partial class </span><span style="color:#2b91af">Workflow1 </span>: <span style="color:#2b91af">SequentialWorkflowActivity </span>{ <span style="color:#0000ff">public </span>Workflow1() { InitializeComponent(); } <span style="color:#0000ff">private string </span>message; <span style="color:#0000ff">public string </span>Message { <span style="color:#0000ff">get </span>{ <span style="color:#0000ff">return </span>message; } } <span style="color:#0000ff">private void </span>codeActivityHello_ExecuteCode(<span style="color:#0000ff">object </span>sender, <span style="color:#2b91af">EventArgs </span>e) { <span style="color:#0000ff">this</span>.message = <span style="color:#a31515">"Hello world"</span>; } }</span></span>

当工作流执行的时候,他就给Workflow1类所实例化的对象中的Message属性赋值为Hello world。我们需要做的是将这个Message获取出来。

先让我们来看看本质,其实,在工作流的对象中,所有的属性都是以键值对的形式存储在哈希表中,因此,我们可以通过WorkflowCompleteEventArgs参数将对应的属性得到,代码如下:

<span style="color:#555555"><span style="background-color:#ffffff"><span style="color:#0000ff">string </span>message = <span style="color:#2b91af">String</span>.Empty; workflowRuntime.WorkflowCompleted += <span style="color:#0000ff">delegate</span>(<span style="color:#0000ff">object </span>sender, <span style="color:#2b91af">WorkflowCompletedEventArgs </span>e) { message = e.OutputParameters[<span style="color:#a31515">"Message"</span>].ToString(); waitHandle.Set(); };</span></span>

接下来,我们就可以打印出message了。

<span style="color:#555555"><span style="background-color:#ffffff"><span style="color:#2b91af">WorkflowInstance </span>instance = workflowRuntime.CreateWorkflow(<span style="color:#0000ff">typeof</span>(WorkflowConsoleApplication3.<span style="color:#2b91af">Workflow1</span>)); instance.Start(); waitHandle.WaitOne(); <span style="color:#2b91af">Console</span>.WriteLine(message);</span></span>

​编辑

8. 进一步改造程序

既然我们可以获得参数,当然也可以向工作流中传入参数。

让我们先来改造一下workflow1.cs的后台代码文件:

<span style="color:#555555"><span style="background-color:#ffffff"><span style="color:#0000ff">public sealed partial class </span><span style="color:#2b91af">Workflow1 </span>: <span style="color:#2b91af">SequentialWorkflowActivity </span>{ <span style="color:#0000ff">public </span>Workflow1() { InitializeComponent(); } <span style="color:#0000ff">private string </span>message; <span style="color:#0000ff">public string </span>Message { <span style="color:#0000ff">get </span>{ <span style="color:#0000ff">return </span>message; } } <span style="color:#0000ff">private string </span>input; <span style="color:#0000ff">public string </span>Input { <span style="color:#0000ff">set </span>{ input = <span style="color:#0000ff">value</span>; } } <span style="color:#0000ff">private void </span>codeActivityHello_ExecuteCode(<span style="color:#0000ff">object </span>sender, <span style="color:#2b91af">EventArgs </span>e) { <span style="color:#0000ff">this</span>.message = <span style="color:#a31515">"Hello " </span>+ input; } }</span></span>

向工作流中传入参数其实很简单,让我们来注意一下这个方法:

<span style="color:#555555"><span style="background-color:#ffffff"><span style="color:#2b91af">WorkflowInstance </span>instance = workflowRuntime.CreateWorkflow(<span style="color:#0000ff">typeof</span>(WorkflowConsoleApplication3.<span style="color:#2b91af">Workflow1</span>)); </span></span>

这个方法通过传入一个类型来实例化一个对应的工作流实例,当然,我们就是运用这个方法的重载方法去传入对应的实例:

<span style="color:#555555"><span style="background-color:#ffffff"><span style="color:#2b91af">Console</span>.WriteLine(<span style="color:#a31515">"Please input your name:"</span>); <span style="color:#0000ff">string </span>input = <span style="color:#2b91af">Console</span>.ReadLine(); <span style="color:#2b91af">Dictionary</span><<span style="color:#0000ff">string</span>, <span style="color:#0000ff">object</span>> dic = <span style="color:#0000ff">new </span><span style="color:#2b91af">Dictionary</span><<span style="color:#0000ff">string</span>, <span style="color:#0000ff">object</span>>(); dic.Add(<span style="color:#a31515">"Input"</span>, input); <span style="color:#2b91af">WorkflowInstance </span>instance = workflowRuntime.CreateWorkflow(<span style="color:#0000ff">typeof</span>(WorkflowConsoleApplication3.<span style="color:#2b91af">Workflow1</span>),dic); instance.Start(); waitHandle.WaitOne(); <span style="color:#2b91af">Console</span>.WriteLine(message);</span></span>
http://www.jsqmd.com/news/567453/

相关文章:

  • 【C盘清理指南】哪些系统文件夹可安全删除,哪些必须保留
  • 深入解析RK3576 Android14中camera3_profiles_rkxxxx.xml的自定义数据格式支持
  • LiuJuan20260223Zimage部署后的持续集成:与CI/CD工具(如Jenkins)联动教程
  • 手把手教你用PHY6252这颗蓝牙5.2芯片,做个超低功耗的智能手环原型
  • AI专家称技术岗位不会消失,程序员也无需担忧
  • AI绘画模型训练完全指南:3大核心优势与零代码实践
  • AcFunDown:A站视频下载神器,轻松保存你喜欢的二次元内容
  • 为“星星的孩子”照亮前路:自闭症干预指南 - 品牌测评鉴赏家
  • 企业级低代码平台JeecgBoot全攻略:从零基础到实战应用
  • Cadence Virtuoso IC617实战:从仿真曲线到SMIC 0.18um工艺库参数提取(保姆级避坑指南)
  • Z-Image-Turbo-辉夜巫女技术解析:Z-Image-Turbo基座+辉夜LoRA微调效果实测
  • 基于零信任架构的分布式浏览器沙箱隔离解决方案:BrowserBox技术深度解析
  • MATLAB安装疑难杂症全攻略:从排查到修复的完整指南(附实用代码)
  • 设计标注工具:解决团队协作痛点的高效解决方案
  • BEAST 2进化分析技术突破与实战指南
  • 软件设计师考试 - Gantt图与PERT图(项目管理)
  • Python调用天擎API下载雷达数据实战:从接口申请到批量下载完整流程
  • 深入解析STM32F103 USB中断处理机制:从寄存器到实战应用
  • 从实验室到生产线:用两台Franka Emika Panda搭建低成本双臂研究平台的完整避坑指南
  • 解决部署难题:Meta-Llama-3-8B-Instruct常见报错分析与避坑指南
  • 如何在无网络环境实现多语言翻译?Argos Translate全平台解决方案
  • 【实验原理深度解析】弗兰克-赫兹实验:如何用电子“碰撞”揭示原子能级的秘密
  • 星星的孩子,不孤单的旅程:揭秘自闭症康复机构 - 品牌测评鉴赏家
  • 如何在Windows系统中实现Btrfs分区的无缝读写?揭秘开源驱动的跨平台方案
  • SQL优化从入门到精通!
  • 2026年 老化房厂家推荐排行榜:高温老化房、恒温老化房,专业定制与稳定性能深度解析 - 品牌企业推荐师(官方)
  • Kandinsky-5.0-I2V-Lite-5s Web工具无障碍设计:支持键盘导航与屏幕阅读器
  • 在WS2812项目中实现高效RGB与HSV色彩空间转换
  • 西安自闭症训练机构大揭秘,为“星星的孩子”照亮前行路 - 品牌测评鉴赏家
  • 题解:洛谷 P14362 [CSP-S 2025] 道路修复