坚持学习WF(6):开发可复用的宿主程序

简介:

我们之前写工作流宿主程序一般都是直接写在program.cs文件里,这样复用性比较差。我们就简单的写两个类,这两个类主要实现的是对WorkflowInstance和WorkflowRuntime的封装。我们以后的例子都会使用这两个类。

第一个类是WorkflowInstanceWrapper,代码如下:


 
 
[Serializable]
     public  class WorkflowInstanceWrapper
    {
         private WorkflowInstance _workflowInstance;
         private ManualResetEvent _waitHandle =  new ManualResetEvent( false);
         private Dictionary<String, Object> _outputParameters=  new Dictionary
                < stringobject>();
         private Exception _exception;
         private String _reasonSuspended = String.Empty;

         public WorkflowInstanceWrapper(WorkflowInstance instance)
        {
            _workflowInstance = instance;
        }        
         public Guid Id
        {
             get
            {
                 if (_workflowInstance !=  null)
                    return _workflowInstance.InstanceId;
                 else
                    return Guid.Empty;
            }
        }        
         public Dictionary<String, Object> OutputParameters
        {
             get {  return _outputParameters; }
             set { _outputParameters = value; }
        }        
         public ManualResetEvent WaitHandle
        {
             get {  return _waitHandle; }
             set { _waitHandle = value; }
        }        
         public Exception Exception
        {
             get {  return _exception; }
             set { _exception = value; }
        }        
         public String ReasonSuspended
        {
             get {  return _reasonSuspended; }
             set { _reasonSuspended = value; }
        }        
         public WorkflowInstance WorkflowInstance
        {
             get {  return _workflowInstance; }
        }        
         public  void StopWaiting()
        {
            _waitHandle.Set();
        }
    }

1._exception,_reasonSuspended:表示当工作流非正常终止或挂起时的相关信息。
2. OutputParameters:用来接收工作流的输出参数,工作流运行时引擎将引发 WorkflowCompleted事件。
工作流运行时引擎将在WorkflowCompletedEventArgs 中传入工作流的所有输出参数。 这些参数包括工作
流的 out 和 ref 参数。
 

第二类是WorkflowManager代码如下:  

  public  class WorkflowRuntimeManager : IDisposable
    {
         private WorkflowRuntime _workflowRuntime;
         private Dictionary<Guid, WorkflowInstanceWrapper> _workflows
                               =  new Dictionary<Guid, WorkflowInstanceWrapper>();
      
         public WorkflowRuntimeManager(WorkflowRuntime instance)
        {
            _workflowRuntime = instance;
             if (instance ==  null)
            {
                 throw  new NullReferenceException(
                     " A non-null WorkflowRuntime instance is required ");
            }            
            SubscribeToEvents(instance);
        }

      
         public WorkflowInstanceWrapper StartWorkflow(Type workflowType,
            Dictionary<String, Object> parameters)
        {
            WorkflowInstance instance = _workflowRuntime.CreateWorkflow(
                workflowType, parameters);
            WorkflowInstanceWrapper wrapper
                = AddWorkflowInstance(instance);
            instance.Start();
             return wrapper;
        }
        
         public WorkflowInstanceWrapper StartWorkflow(String markupFileName,
            String rulesMarkupFileName,
            Dictionary<String, Object> parameters)
        {
            WorkflowInstance instance =  null;
            WorkflowInstanceWrapper wrapper =  null;
            XmlReader wfReader =  null;
            XmlReader rulesReader =  null;
             try
            {
                wfReader = XmlReader.Create(markupFileName);
                 if (!String.IsNullOrEmpty(rulesMarkupFileName))
                {
                    rulesReader = XmlReader.Create(rulesMarkupFileName);
                    instance = _workflowRuntime.CreateWorkflow( wfReader, rulesReader, parameters);
                }
                 else
                {
                    instance = _workflowRuntime.CreateWorkflow(wfReader,  null, parameters);
                }
                wrapper = AddWorkflowInstance(instance);
                instance.Start();
            }
             finally
            {
                 if (wfReader !=  null)
                {
                    wfReader.Close();
                }
                 if (rulesReader !=  null)
                {
                    rulesReader.Close();
                }
            }
             return wrapper;
        }

        public WorkflowRuntime WorkflowRuntime
        {
             get {  return _workflowRuntime; }
        }        
         public Dictionary<Guid, WorkflowInstanceWrapper> Workflows
        {
             get {  return _workflows; }
        }        
         public  event EventHandler<WorkflowLogEventArgs> MessageEvent;    

       
         public  void ClearWorkflow(Guid workflowId)
        {
             if (_workflows.ContainsKey(workflowId))
            {
                _workflows.Remove(workflowId);
            }
        }
      
         public  void ClearAllWorkflows()
        {
            _workflows.Clear();
        }
       
         private WorkflowInstanceWrapper AddWorkflowInstance(
            WorkflowInstance instance)
        {
            WorkflowInstanceWrapper wrapper =  null;
             if (!_workflows.ContainsKey(instance.InstanceId))
            {
                wrapper =  new WorkflowInstanceWrapper(instance);
                _workflows.Add(wrapper.Id, wrapper);
            }
             return wrapper;
        }
     
         public WorkflowInstanceWrapper FindWorkflowInstance(Guid workflowId)
        {
            WorkflowInstanceWrapper result =  null;
             if (_workflows.ContainsKey(workflowId))
            {
                result = _workflows[workflowId];
            }
             return result;
        }
       
         public  void WaitAll(Int32 msecondsTimeout)
        {
             if (_workflows.Count >  0)
            {
                WaitHandle[] handles =  new WaitHandle[_workflows.Count];
                Int32 index =  0;
                 foreach (WorkflowInstanceWrapper wrapper
                     in _workflows.Values)
                {
                    handles[index] = wrapper.WaitHandle;
                    index++;
                }
                WaitHandle.WaitAll(handles, msecondsTimeout,  false);
            }
        }
     
         public  void Dispose()
        {
             if (_workflowRuntime !=  null)
            {
                _workflowRuntime.StopRuntime();
                _workflowRuntime.Dispose();
            }
            ClearAllWorkflows();
        }
      
         private  void SubscribeToEvents(WorkflowRuntime runtime)
        {
            runtime.Started +=  new EventHandler<WorkflowRuntimeEventArgs>( runtime_Started);
            runtime.Stopped +=  new EventHandler<WorkflowRuntimeEventArgs>(runtime_Stopped);
            runtime.WorkflowAborted+= ......
            runtime.WorkflowCompleted+= ......
            runtime.WorkflowCreated += ......   
            ............
        }

         void runtime_Started( object sender, WorkflowRuntimeEventArgs e)
        {
            LogStatus(Guid.Empty,  " Started ");
        }
         void runtime_Stopped( object sender, WorkflowRuntimeEventArgs e)
        {
            LogStatus(Guid.Empty,  " Stopped ");
        }
         void runtime_WorkflowCreated( object sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId,  " WorkflowCreated ");
        }
         void runtime_WorkflowStarted( object sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId,  " WorkflowStarted ");
        }
         void runtime_WorkflowIdled( object sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId,  " WorkflowIdled ");
        }

         void runtime_WorkflowCompleted( object sender, WorkflowCompletedEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId,  " WorkflowCompleted ");
            WorkflowInstanceWrapper wrapper
                = FindWorkflowInstance(e.WorkflowInstance.InstanceId);
             if (wrapper !=  null)
            {
                wrapper.OutputParameters = e.OutputParameters;
                wrapper.StopWaiting();
            }
        }

         void runtime_WorkflowTerminated( object sender,
            WorkflowTerminatedEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId,  " WorkflowTerminated ");
            WorkflowInstanceWrapper wrapper = FindWorkflowInstance(e.WorkflowInstance.InstanceId);
             if (wrapper !=  null)
            {
                wrapper.Exception = e.Exception;
                wrapper.StopWaiting();
            }
        }

         void runtime_WorkflowSuspended( object sender, WorkflowSuspendedEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId,  " WorkflowSuspended ");
            WorkflowInstanceWrapper wrapper = FindWorkflowInstance(e.WorkflowInstance.InstanceId);
             if (wrapper !=  null)
            {
                wrapper.ReasonSuspended = e.Error;
            }
        }

         void runtime_WorkflowResumed( object sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId,  " WorkflowResumed ");
        }
         void runtime_WorkflowPersisted( object sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId,  " WorkflowPersisted ");
        }
         void runtime_WorkflowLoaded( object sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId,  " WorkflowLoaded ");
        }
         void runtime_WorkflowAborted( object sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId,  " WorkflowAborted ");
            WorkflowInstanceWrapper wrapper
                = FindWorkflowInstance(e.WorkflowInstance.InstanceId);
             if (wrapper !=  null)
            {
                wrapper.StopWaiting();
            }
        }

         void runtime_WorkflowUnloaded( object sender, WorkflowEventArgs e)
        {
            LogStatus(e.WorkflowInstance.InstanceId,  " WorkflowUnloaded ");
        }

         private  void LogStatus(Guid instanceId, String msg)
        {
             if (MessageEvent !=  null)
            {
                String formattedMsg;
                 if (instanceId == Guid.Empty)
                {
                    formattedMsg = String.Format( " Runtime - {0} ", msg);
                }
                 else
                {
                    formattedMsg = String.Format( " {0} - {1} ", instanceId, msg);
                }
                 // raise the event
                MessageEvent( thisnew WorkflowLogEventArgs(formattedMsg));
            }
        }

    }   
     public  class WorkflowLogEventArgs : EventArgs
    {
         private String _msg = String.Empty;
         public WorkflowLogEventArgs(String msg)
        {
            _msg = msg;
        }

         public String Message
        {
             get {  return _msg; }
        }

1._workflows:一个key为Guid,value为WorkflowInstanceWrapper的字典。
2.SubscribeToEvent():给workflowRuntime订阅事件.
3.StartWorkflow():实现创建,开始工作流.
4.MessageEvent:对Message进行格式化。
5.WaitAll()用来挂起当前的线程直到所有的workflows完成,每个WorkflowInstanceWrapper有一个WaitHandle属性以便宿主程序能灵活控制。 

下面是测试代码:

 
 
using (WorkflowRuntimeManager manager
        =  new WorkflowRuntimeManager( new WorkflowRuntime( " WorkflowRuntime ")))
{
   manager.MessageEvent +=  delegate(Object sender, WorkflowLogEventArgs e)
   {
      Console.WriteLine(e.Message);
   };
   manager.WorkflowRuntime.StartRuntime();
   Dictionary<String, Object> wfArguments=  new Dictionary< stringobject>();
   wfArguments.Add( " InputString "" one ");
   WorkflowInstanceWrapper instance = manager.StartWorkflow(
            typeof(SharedWorkflows.Workflow1), wfArguments);
   instance.WorkflowInstance.Terminate( " Manually terminated ");
   instance.WaitHandle.WaitOne( 10000false);
    foreach (WorkflowInstanceWrapper wrapperin manager.Workflows.Values)
   {
        if (wrapper.OutputParameters.ContainsKey( " Result "))
       {
            Console.WriteLine(wrapper.OutputParameters[ " Result "]);
       }
        if (wrapper.Exception !=  null)
       {
     Console.WriteLine( " {0}-Exception:{1} ",wrapper.Id,wrapper.Exception.Message);
       }
        if (wrapper.ReasonSuspended.Length >  0)
       {
    Console.WriteLine( " {0}-Suspended: {1} ",wrapper.Id, wrapper.ReasonSuspended);
       }
}    manager.ClearAllWorkflows();























下面运行结果,从该结果可以清晰的看出工作流的执行过程:


1
 上一篇:坚持学习WF(5):自定义活动(CustomActivity) 
下一篇:坚持学习WF(7):流程控制(Flow Control)



本文转自生鱼片博客园博客,原文链接:http://www.cnblogs.com/carysun/archive/2008/04/21/1164609.html,如需转载请自行联系原作者

目录
相关文章
|
6天前
|
人工智能 运维 BI
阿里云千问办公QwenWork深度解析:基于Qwen3.8,六大核心能力重构企业全自动化工作流与计费选型指南
传统AI办公工具大多停留在对话问答、文档摘要、简单文案生成层面,只能完成单点碎片化任务,无法自主拆解复杂业务流程,很难串联多工具、多文档、外部业务系统完成端到端完整工作交付。很多企业在落地AI办公的时候,需要组合多款不同工具,来回切换界面,手动复制粘贴中间结果,智能化改造落地门槛居高不下。千问办公QwenWork是整合多款智能体产品能力打造的一体化企业办公智能体平台,底层基座依托Qwen3.8大模型,打通桌面端Agent、云端Agent、企业协同Agent三种运行形态,不再局限简单问答,接收业务目标之后自主拆解任务步骤,调用各类工具,处理文档、表格、浏览器自动化、数据查询,直接输出可交付的办公
1524 0
|
6天前
|
人工智能 自然语言处理 安全
阿里云AI数智鉴密:AI 生成内容如何拿到一张"防篡改的身份证"
隐形水印 + C2PA签名:让AI生成内容“持证上岗”。
1135 0
|
15天前
|
人工智能 自然语言处理 安全
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
本文聚焦阿里云2026年推出的三款自研AI办公产品,清晰拆解千问办公、Qoder Teams、Qoder CN的差异化定位与能力边界:千问办公主打职场全场景提效,支持自然语言指令一键完成PPT生成、数据分析等高频办公任务;Qoder Teams面向程序员团队,深度整合AI代码生成、团队协同与企业知识库能力;Qoder CN则专为金融、政务等强合规场景打造,实现数据不出境与VPC私有化部署。文章同步给出分场景选型指南与最新活动定价,帮助不同类型的企业按需组合产品,实现业务岗、研发岗与强合规场景的AI能力全覆盖。
3804 4
阿里云千问办公、Qoder Teams、Qoder CN区别与选择指南:模型能力、适用场景与最新活动参考
|
3天前
|
SQL 人工智能 前端开发
QoderWake 1.0 正式发布:从桌面里的 Agent,到工作现场的数字员工
QoderWake v1.0正式发布:企业级数字员工团队平台。支持“一句话建岗”,预置10类特训岗位;Waker常驻钉钉/飞书群,@即响应、自动协作、跨任务记忆;具备定时/事件/API多触发方式与统一任务看板;已沉淀27.6万条记忆、12.3万项技能,助力组织实现人机协同增效。
655 0
|
2天前
|
人工智能 API 内存技术
刚刚 DeepSeek V4.1 Flash 开启内测,1 分钟教你用上!
刚刚 DeepSeek 内测群发布了 DeepSeek V4.1 Flash 中间版本内测的消息,这次的模型采用了新的结构,原生支持多模态、能力更强、速度更快、且成本更低。
1478 2
|
7天前
|
网络协议 Linux iOS开发
【2026实测】Wireshark下载+安装+汉化+使用教程(图文版,巨详细)
Wireshark 是一款免费开源的网络协议分析工具,可实时捕获、解析并可视化数据包,助你诊断网络故障、分析通信协议(如HTTP、DNS、TCP等)。支持Windows/macOS/Linux,含中文界面,新手入门便捷。(239字)