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

Workflow笔记2——状态机工作流

状态机工作流

    在上一节Workflow笔记1——工作流介绍中,介绍的是流程图工作流,后来微软又推出了状态机工作流,它比流程图功能更加强大。

    状态机工作流:就是将工作流系统中的所有的工作节点都可以看做成一个状态节点。每个节点都有N个状态,其中都包含初始状态、进入状态、离开状态等。当节点的状态变化的时候会执行某个节点。

    新建项目StatueWorkflowConsoleApp

    自动添加了一个起始节点和一个状态节点.

 

 

    运行结果如下:

    注意执行顺序。接下来,扩展此工作流。

    1、设置全局变量Num

    2、双击T1,为变量Num赋值

 

new Random().Next(0,10)

    运行结果如下:

启动工作流

    之前我们新建的工作流项目,都是通过如下方式来启动工作流的。

            Activity workflow1 = new Workflow1();
            WorkflowInvoker.Invoke(workflow1);

    而在工作中,我们通常不能通过这样的方式来启动工作流。因为我们的流程启动后,我需要监控流程的各种状态。而我们通过Invoke的方式启动工作流,是无法监控工作流的状态的。我们可以通过WorkflowApplication类启动工作流。参考:https://msdn.microsoft.com/zh-cn/library/system.activities.workflowapplication(v=vs.110).aspx

    WorkflowInvoker 包含同步调用工作流的实例方法和静态方法。WorkflowInvoker 不允许实例控件,如保持、卸载或恢复书签。

    WorkflowApplication 类为单个工作流实例提供宿主。 它是由工作流运行时管理的实际工作流实例的代理。

  • 创建新的工作流实例,或从实例存储区中加载工作流实例。
  • 提供扩展以供工作流实例内的活动使用。
  • 控制工作流实例的执行。
  • 恢复由工作流实例内的活动创建的书签。
  • 保留或卸载工作流实例。
  • 接收工作流实例生命周期事件通知。

    1、新建Windows窗体应用程序,WindowsWorkFlowApp

    2、右键单击项目WindowsWorkFlowApp,新建活动,添加状态机

    3、双击State1,添加输入参数

    4、再添加一个状态和结束状态

    5、双击FinalState,在其中添加输出

    修改State2

    6、修改“启动工作流”按钮的事件代码如下:

复制代码
        private void btnStartWorkFlow_Click(object sender, EventArgs e)
        {
            WorkflowApplication app = new WorkflowApplication(new Activity1(), new Dictionary<string, object>() { 
            {"InputName","神刀张三"}
            });
            app.Run();
        }
复制代码

    我们来看下WorkflowApplication的构造函数。

构造函数

名称

说明

WorkflowApplication(Activity)

使用指定的工作流定义创建 WorkflowApplication 类的新实例。

WorkflowApplication(Activity, IDictionary<String, Object>)

创建 WorkflowApplication 类的新实例,该实例使用指定的工作流定义和参数值。

WorkflowApplication(Activity, IDictionary<String, Object>, WorkflowIdentity)

创建的新实例 WorkflowApplication 类,该类使用指定的工作流定义和参数值和定义标识。

WorkflowApplication(Activity, WorkflowIdentity)

创建的新实例 WorkflowApplication 使用指定的工作流定义和定义标识的类。

    7、由于我创建的是Windows应用程序,那么要想输出控制台信息,我们必须修改项目的输出方式

    8、运行项目

WorkflowApplication生命周期

    那么我们如何来监控工作流的状态呢,我们可以使用指定的工作流定义构造 WorkflowApplication,处理所需的工作流生命周期事件,并通过调用 Run 来调用工作流。

在Run方法调用之前,我们来注册生命周期事件,添加代码如下:

复制代码
 #region 工作流生命周期事件
            app.Unloaded = delegate(WorkflowApplicationEventArgs er)
              {
                  Console.WriteLine("工作流 {0} 卸载.", er.InstanceId);
              };
            app.Completed = delegate(WorkflowApplicationCompletedEventArgs er)
            {
                Console.WriteLine("工作流 {0} 完成.", er.InstanceId);
            };
            app.Aborted = delegate(WorkflowApplicationAbortedEventArgs er)
            {
                Console.WriteLine("工作流 {0} 终止.", er.InstanceId);
            };
            app.Idle = delegate(WorkflowApplicationIdleEventArgs er)
            {
                Console.WriteLine("工作流 {0} 空闲.", er.InstanceId);
            };
            app.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs er)
            {
                Console.WriteLine("持久化");
                return PersistableIdleAction.Unload;
            };
            app.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs er)
            {
                Console.WriteLine("OnUnhandledException in Workflow {0}\n{1}",
       er.InstanceId, er.UnhandledException.Message);
                return UnhandledExceptionAction.Terminate;
            }; 
            #endregion
复制代码

    再次运行项目,结果如下:

多线程信号量机制

    Run方法会开启一个新的线程。而通常,我们需要等待工作流运行完成之后再回到主线程。那么我们可以使用AutoResetEvent一个线程通过调用等待一个信号 WaitOne 上 AutoResetEvent

在工作流实例化之前,就创建一个AutoResetEvent对象。

AutoResetEvent syncEvent = new AutoResetEvent(false);

    然后在工作流的Completed事件中,执行Set方法,将事件状态设置为有信号,从而允许一个或多个等待线程继续执行,说白了就是一个唤醒操作。

syncEvent.Set();

    最后在Run方法的后面,添加

syncEvent.WaitOne();

    WaitOne方法将阻止当前线程,直到当前 WaitHandle 收到信号,从而实现等待工作流线程运行完成的功能。

    源码下载:WorkflowConsoleApp2.zip


本文转自邹琼俊博客园博客,原文链接:http://www.cnblogs.com/jiekzou/p/6192813.html,如需转载请自行联系原作者

相关文章:

  • Octoroit OS VB操作系统简单介绍
  • 【C#】与C及OC的不同点
  • 10个小技巧帮助Devops走向成功
  • [UVA 11825] Hackers' Crackdown
  • Springboot集成Mybatis
  • 11.32 php扩展模块安装
  • vue跨域解决方法
  • 关于android Activity的 theme
  • HTTP 07 追加协议与 Ajax
  • Javascript 面向对象编程—继承和封装
  • 沃土前端社区教程 - es6(7)常用技能点
  • MATH
  • EXTJS学习系列基础篇:第二篇(转载)作者殷良胜
  • 一卡通vip充值消费线上oracle库服务器故障排查过程
  • 通过UseAfterFree实现命令执行
  • JavaScript 如何正确处理 Unicode 编码问题!
  • [译]Python中的类属性与实例属性的区别
  • 《剑指offer》分解让复杂问题更简单
  • 4. 路由到控制器 - Laravel从零开始教程
  • ES6系统学习----从Apollo Client看解构赋值
  • javascript 总结(常用工具类的封装)
  • Magento 1.x 中文订单打印乱码
  • miaov-React 最佳入门
  • Redis的resp协议
  • Twitter赢在开放,三年创造奇迹
  • VUE es6技巧写法(持续更新中~~~)
  • vue-router的history模式发布配置
  • vue的全局变量和全局拦截请求器
  • Vue组件定义
  • 闭包,sync使用细节
  • 从输入URL到页面加载发生了什么
  • 分布式任务队列Celery
  • 后端_MYSQL
  • 漂亮刷新控件-iOS
  • 通过获取异步加载JS文件进度实现一个canvas环形loading图
  • 消息队列系列二(IOT中消息队列的应用)
  • 怎么把视频里的音乐提取出来
  • 《码出高效》学习笔记与书中错误记录
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • 仓管云——企业云erp功能有哪些?
  • ​2020 年大前端技术趋势解读
  • ###51单片机学习(1)-----单片机烧录软件的使用,以及如何建立一个工程项目
  • (+4)2.2UML建模图
  • (4)事件处理——(2)在页面加载的时候执行任务(Performing tasks on page load)...
  • (附源码)计算机毕业设计ssm基于Internet快递柜管理系统
  • (原創) 物件導向與老子思想 (OO)
  • (转)C#调用WebService 基础
  • (轉貼) 資訊相關科系畢業的學生,未來會是什麼樣子?(Misc)
  • .NET 4.0中的泛型协变和反变
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .Net Remoting(分离服务程序实现) - Part.3
  • .NET 服务 ServiceController
  • .Net 知识杂记
  • .Net(C#)自定义WinForm控件之小结篇
  • .NET/C# 解压 Zip 文件时出现异常:System.IO.InvalidDataException: 找不到中央目录结尾记录。