应用示例:流程控制

本章节以简易业务场景为例,介绍如何通过全局脚本模块定义多个流程的执行逻辑。

本节内容包含:

方案需求

假设针对某视觉业务场景的方案中原本已搭建了3个流程,分别为流程1、流程2和流程3。随着业务的发展,现需要实现如下多流程控制需求:流程1和流程2都执行1次(不分先后)之后,触发流程3自动执行1次。

由于VM支持执行单个流程和批量执行方案下所有流程,该需求可进一步拆分为2个子需求:

表 1 子需求

子需求

描述

子需求1

流程1和流程2分别执行1次(不分先后)之后,触发流程3自动执行1次。

子需求2

流程1、流程2和流程3批量执行1次后,触发流程3自动执行1次。

方案思路

方案中多个流程的执行逻辑,可通过全局脚本实现。

具体的实现途径见下图。

图 1 实现途径

方案搭建

基于上述思路,需自行开发全局脚本的代码逻辑实现多流程控制的需求。

已在方案中的搭建3个流程。

说明:

本节仅就全局脚本中涉及的核心接口调用做简要介绍。其中SDK的类、方法和属性的详情,请参见VM的SDK开发指南(.NET)。

  1. 单击快捷工具条上的打开全局脚本窗口,准备开始C#编程。
  2. 调用全局脚本的Init方法,在该方法中声明流程1、流程2和流程2的句柄,实现全局脚本的初始化。
  3. 调用全局脚本的InitAfterLoadSol方法,实现在方案加载结束时对流程1、流程2和流程3进行初始化。
  4. InitAfterLoadSol方法中,为流程1和流程2注册.NET SDK的OnWorkEndStatusCallBack回调函数。该回调函数用于在流程执行结束时触发“流程执行结束”事件。
  5. 调用.NET SDK的OnWorkEndStatusCallBack(object sender, EventArgs e)方法获取流程1和流程2执行结束事件的数据,并在该方法中实现多流程执行逻辑。
    1. 自行定义流程1和流程2执行结束状态的变量,并自行实现流程执行状态的判断逻辑(即流程1和流程2都执行1次后再执行1次流程3)。
    2. 调用.NET SDK的Run方法,异步执行1次流程3。

    示例代码如下:

        private void Pro1_OnWorkEndStatusCallBack(object sender, EventArgs e)
        {
            if (e != null)
            {
                ValueEventArgs eventArgs = (ValueEventArgs)e;
                ImvsSdkDefine.IMVS_MODULE_WORK_STAUS status = (ImvsSdkDefine.IMVS_MODULE_WORK_STAUS)eventArgs.Value;
                //流程1执行完成
                if (status.nProcessID == 10000)
                {
                    pro1RunEnd = true;
                }
                else if (status.nProcessID == 10001)
                {
                    pro2RunEnd = true;
                }
                else if (status.nProcessID == 10002)
                {
                    pro1RunEnd = false;
                    pro2RunEnd = false;
                }
                if (pro1RunEnd && pro2RunEnd)
                {
                    //异步执行一次
                    pro3.Run("", false);
                }
            }
        }
    说明:

    以上示例中的nProcessID为SDK中定义“流程ID”的属性,属于ModuleResult.ModulInfo结构体。“流程ID”可从软件界面的如下路径获取:

    图 2 流程ID获取
  6. 调用全局脚本的Dispose方法,释放流程1和流程2的执行结束事件回调所占用的资源。

    至此,已实现“子需求1”。

  7. 调用全局脚本的Process方法,实现方案下所有流程在单击批量执行按钮时同时执行1次。

    该方法的逻辑与上述步骤实现逻辑共同生效,即实现“子需求2”。

上述步骤的完整示例代码如下:

using System;
using VM.GlobalScript.Methods;
using System.Windows.Forms;
using iMVS_6000PlatformSDKCS;
using System.Runtime.InteropServices;
using VM.Core;
using VM.PlatformSDKCS;
using ImageSourceModuleCs;
using IMVSCircleFindModuCs;
using VMControls.Interface;
using System.Drawing;
using System.Drawing.Imaging;
using System.Threading.Tasks;
/*****************************************
 * Example explanation:Example of multi process control operation
 * Logic Control:Single run, each flow execute once
 * Continuous run:continuous run, each flow execute continuous
 * 示例说明: 默认代码
 * 控制逻辑: 单次运行:所有流程运行一次
 *           连续运行:所有流程连续运行
 * ***************************************/
public class UserGlobalScript : UserGlobalMethods, IScriptMethods
{
    /// <summary>
    /// Init
    /// </summary>
    /// <returns>Success:return 0</returns>
    public int Init()
    {
        //SDK init
        int ret = InitSDK();
        //InitAfterLoadSol();
        if(pro1==null)
        {pro1 = (VmProcedure)VmSolution.Instance["流程1"];}
        if(pro2==null)
        {pro2 = (VmProcedure)VmSolution.Instance["流程2"];}
        if (pro3 == null)
        { pro3 = (VmProcedure)VmSolution.Instance["流程3"]; }
        return ret;
    }

    private VmProcedure pro1 = null;
    private VmProcedure pro2 = null;
    private VmProcedure pro3 = null;
    private bool pro1RunEnd = false;
    private bool pro2RunEnd = false;

    //加载方案完成触发动作
    public override int InitAfterLoadSol()
    {
    	if(pro1==null)
        {pro1 = (VmProcedure)VmSolution.Instance["流程1"];}
        if (pro1 != null)
        {
            pro1.OnWorkEndStatusCallBack += Pro1_OnWorkEndStatusCallBack;
        }
        if (pro2 == null)
        { pro2 = (VmProcedure)VmSolution.Instance["流程2"]; }
        if (pro2 != null)
        {
            pro2.OnWorkEndStatusCallBack += Pro1_OnWorkEndStatusCallBack;
        }
        if (pro3 == null)
        { pro3 = (VmProcedure)VmSolution.Instance["流程3"]; }
        return 0;
    }
    
    private void Pro1_OnWorkEndStatusCallBack(object sender, EventArgs e)
    {
        if (e != null)
        {
            ValueEventArgs eventArgs = (ValueEventArgs)e;
            ImvsSdkDefine.IMVS_MODULE_WORK_STAUS status = (ImvsSdkDefine.IMVS_MODULE_WORK_STAUS)eventArgs.Value;
            //流程1执行完成
            if (status.nProcessID == 10000)
            {
                pro1RunEnd = true;
            }
            else if (status.nProcessID == 10001)
            {
                pro2RunEnd = true;
            }
            else if (status.nProcessID == 10002)
            {
                pro1RunEnd = false;
                pro2RunEnd = false;
            }
            if (pro1RunEnd && pro2RunEnd)
            {
                //异步执行一次
                pro3.Run("", false);
            }
        }
    }

    public override void Dispose()
    {
        base.Dispose();
        if (pro1 != null)
        {
            pro1.OnWorkEndStatusCallBack -= Pro1_OnWorkEndStatusCallBack;
        }
        if (pro2 != null)
        {
            pro2.OnWorkEndStatusCallBack -= Pro1_OnWorkEndStatusCallBack;
        }
    }

    /// <summary>
    /// execute function
    /// Single run:the function execute once
    /// Continuous run:Repeat the function at regular intervals
    /// 运行函数
    /// 单次执行:该函数执行一次
    /// 连续执行:以一定时间间隔重复执行该函数
    /// </summary>
    /// <returns>Success:return 0</returns>
    public int Process()
    {
        //m_operateHandle SDK handle
        if (m_operateHandle == IntPtr.Zero)
        { return ImvsSdkPFDefine.IMVS_EC_NULL_PTR; }

        //All processes are executed by default
        //If execute in your own define logic,please remove the function :DefaultExecuteProcess, Create your own logic function.
        //默认执行全部流程,
        //如果自定义流程执行逻辑,请移除DefaultExecuteProcess方法,编写自定义流程执行逻辑代码
        int nRet = DefaultExecuteProcess();
        return nRet;
    }
}

方案效果测试

完成该方案的搭建后,可在VM软件上测试方案效果。

  • 测试场景1:先执行1次流程1,再执行1次流程2。

    测试结果:触发流程3执行1次(见如下动图)。

    图 3 测试场景1
  • 测试场景2:先执行1次流程2,再执行1次流程1。

    测试结果:触发流程3执行1次(见如下动图)。

    图 4 测试场景2
  • 测试场景3:批量同时执行各流程1次

    测试结果:流程3在和流程1和流程2同时执行1次的基础上,由于流程1和流程2都执行结束,又被触发执行1次。因此最终流程3在该场景总共执行了2次(见如下动图)。

    图 5 测试场景3