WorkFlow工作流

一、WorkFlow介绍

1. WorkFlow是OA系统中必不可少的模块,并且在以后的大多数的工作中,都会用到工作流模式的开发。关于这方面的开发,我第一次接触到的是关于钉钉里的氚云功能,感觉还是做的相当不错,用户只需要拖动控件,然后配置数据库,就会形成对应的工作流,并不需要大量的代码编写。

二、创建一个demo案例:

1. 这儿创建的是一个控制台程序demo。

 主程序代码如下:

using System;
using System.Linq;
using System.Activities;     //主要的
using System.Activities.Statements;

namespace WorkflowConsoleApplication1
{

    class Program
    {
        static void Main(string[] args)
        {
            //new了一个工作流类
            Activity workflow1 = new Workflow1();
            //启动工作流
            WorkflowInvoker.Invoke(workflow1);
            Console.ReadLine();
        }
    }
}

其中需要注意的是inputCodeActivity1,该控件是一个代码活动,就是指此处需要一些别的操作,具体创建如下:

并且编辑如下代码,提供一个返回参数:

    public sealed class inputCodeActivity1 : CodeActivity
    {
        // 定义一个字符串类型的活动输入参数
        //public InArgument<string> Text { get; set; }
        //输出参数
        public OutArgument<int> returnMoney { get; set; }

        // 如果活动返回值,则从 CodeActivity<TResult>
        // 派生并从 Execute 方法返回该值。
        protected override void Execute(CodeActivityContext context)
        {
            // 获取 Text 输入参数的运行时值
            //string text = context.GetValue(this.Text);
            int m;
            string money = Console.ReadLine();
            int.TryParse(money, out m);
            //为输出参数设置参数
            context.SetValue(returnMoney,m);
        }
    }

最终全部创建好,之后,如下:

 最终的运行结果如下:

 备注:4.0版本的没有状态机工作流,需要切换到别的版本才有

三、 WorkflowApplication启用工作流以及传参,与常用触发事件。

1. WorkflowApplication提供了很多的触发事件,每当工作流执行到某一状态的时候,就会触发该工作流里的方法,并且进行实时监控,所以目前工作流的启动,都是使用该类来完成。

2. case:

 定义一个winform窗体应用界面

button对应代码如下:

 private void btnStartWorkFlow_Click(object sender, EventArgs e)
        {
            //定义一个字典
            var dict = new Dictionary<string, object>() { { "tempDateTime", DateTime.Now } };
            //工作流的类,
            //WorkflowApplication wfApp = new WorkflowApplication(new Activity1());
            //重载的第二种,传递一个参数过去,但是必须是键值对的形式。
            WorkflowApplication wfApp = new WorkflowApplication(new Activity1(),dict);
            //信号量机制类
            AutoResetEvent syncEvent = new AutoResetEvent(false);
            wfApp.Run();
        }

工作流中如下:此处的参数必须和传递的参数值一致。

3. 常用触发事件。

 private void btnStartWorkFlow_Click(object sender, EventArgs ex)
        {
            Console.WriteLine("主线程:"+Thread.CurrentThread.ManagedThreadId);
            var dict = new Dictionary<string, object>() { { "TempDateTime", DateTime.Now }, { "TempBookMarkName",this.txtBookMarkName.Text} };
            AutoResetEvent syncEvent = new AutoResetEvent(false);  //主线程信号量
             wfApp = new WorkflowApplication(new Activity1(), dict);//第二个参数是给工作流传参,这里的参数名TempDateTime,必须和工作流中定义的参数名称一致.
            //-----------------------常用触发事件---------------------
            //工作流执行完成之后触发里面代码,
            wfApp.Completed = delegate(WorkflowApplicationCompletedEventArgs e)
            {
                Console.WriteLine("工作流执行完成");
                syncEvent.Set();  //唤起主线程
            };
            //强制终止触发
            wfApp.Aborted = delegate(WorkflowApplicationAbortedEventArgs e)
            {
                Console.WriteLine("工作流终止");
                syncEvent.Set();
            };
            //处于空闲状态触发
            wfApp.Idle = delegate(WorkflowApplicationIdleEventArgs e)
                {
                    Console.WriteLine("工作流空闲");
                    syncEvent.Set();
                };
            //工作流持久化,就是指例如把当前的数据录入到数据库中
            wfApp.PersistableIdle = delegate(WorkflowApplicationIdleEventArgs e)
            {
                Console.WriteLine("工作流持久化");
                syncEvent.Set();
                return PersistableIdleAction.Unload;  //工作流卸载
            };
            //卸载之后触发
            wfApp.Unloaded = delegate(WorkflowApplicationEventArgs e)
            {
                Console.WriteLine("工作流卸载");
                syncEvent.Set();
            };
            //发生异常触发的时间
            wfApp.OnUnhandledException = delegate(WorkflowApplicationUnhandledExceptionEventArgs e)
            {
                Console.WriteLine("工作流异常了");
                syncEvent.Set();
                return UnhandledExceptionAction.Abort;
            };
            // Start the workflow.
            wfApp.Run();//开始执行设计好的工作流,这里会会开启一个新的线程。
            syncEvent.WaitOne();  //阻止主线程,直到当前收到信号。

            Console.WriteLine("继续执行后面的代码");
        }

四、线程信号量类介绍:

1. new一个线程信号量 

 AutoResetEvent syncEvent = new AutoResetEvent(false);  //主线程信号量

上方代码中主要使用到了如下两个方法;

syncEvent.Set();  //唤起主线程
syncEvent.WaitOne();  //阻止主线程,直到当前收到信号。

 五、 BookMark(书签)

1. 就是指执行到该结点处暂停,等待开启的命令,然后继续执行。

2. 就是指修改创建的代码活动类。本来是继承CodeActivity类,现在改为继承NativeActivity,并且重新其中提供的抽象方法,注释掉原本的方法,创建Bookmark书签,需要提供两个参数,一个是书签名,一个是需要执行的方法,相关代码如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Activities;
namespace WindowsFormsApplication1
{
    //修改使其继承 NativeActivity
    public sealed class Wait4BookMarkCodeActivity :NativeActivity
    {
        // 定义一个字符串类型的活动输入参数
        public InArgument<string> BookMarkName { get; set; }
        public OutArgument<int> ReturnResult { get; set; }

        // 如果活动返回值,则从 CodeActivity<TResult>
        // 派生并从 Execute 方法返回该值。
        //protected override void Execute(CodeActivityContext context)
        //{
        //    // 获取 Text 输入参数的运行时值
        //    string text = context.GetValue(this.Text);
        //}

        /// <summary>
        /// 自动调用该方法,在该方法中完成BookMark的创建
        /// </summary>
        /// <param name="context"></param>
        protected override void Execute(NativeActivityContext context)
        {
            //拿到输入参数的值
            string bookMarkName = context.GetValue(BookMarkName);
            //创建bookMark,第一个是他的名字,第二个是传递一个委托事件         ,并且唤醒bookMark。
            //以下等同于,第一个参数是名字,第二个参数是一个方法。
            context.CreateBookmark(bookMarkName, ExecuteContinue);
        }
        protected override bool CanInduceIdle
        {
            get
            {
                return true;
            }
        }
        /// <summary>
        /// 当下次唤起BookMark,那么该方法被执行.
        /// </summary>
        /// <param name="context"></param>
        /// <param name="bookmark"></param>
        /// <param name="value"></param>
        public void ExecuteContinue(NativeActivityContext context, Bookmark bookmark, object value)
        {
            int i = Convert.ToInt32(value);
            context.SetValue(ReturnResult,i);
        }
    }
}
原文地址:https://www.cnblogs.com/wangjinya/p/10924581.html