`

坚持学习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)
分享到:
评论

相关推荐

    WF教程_坚持学习WF

    坚持学习WF(6):开发可复用的宿主程序 主要实现两个类来对WorkflowInstance和WorkflowRuntime进行简单的封装。 坚持学习WF(7):流程控制(Flow Control) 主要说了WF中和流程相关的活动,主要包括以下这些活动:...

    开发可复用的宿主程序

    【开发可复用的宿主程序】在软件开发中,特别是在使用Windows Workflow Foundation (WF) 构建工作流应用时,提高代码复用性是非常重要的。传统的做法是将宿主程序直接编写在`Program.cs`文件中,但这限制了代码的...

    坚持学习WF,WF学习教程

    坚持学习WF(6):开发可复用的宿主程序 主要实现两个类来对WorkflowInstance和WorkflowRuntime进行简单的封装。 坚持学习WF(7):流程控制(Flow Control) 主要说了WF中和流程相关的活动,主要包括以下这些活动:...

    坚持学习WF

    坚持学习WF(6):开发可复用的宿主程序 主要实现两个类来对WorkflowInstance和WorkflowRuntime进行简单的封装。 坚持学习WF(7):流程控制(Flow Control) 主要说了WF中和流程相关的活动,主要包括以下这些活动:...

    wf工作流资料<转自网上的笔记>

    "坚持学习WF(6)开发可复用的宿主程序"则涉及如何将工作流集成到实际应用中,讲解了宿主的概念和如何创建一个能够启动、管理和持久化工作流实例的应用程序。 "坚持学习WF(9)本地服务之事件处理"探讨了WF中的事件处理...

    WF从入门到精通(1-16章)

    - **WF编程入门**:学习如何使用WF进行编程,包括安装必要的开发环境、编写第一个WF应用程序等。 - **Visual Studio工作流支持**:介绍如何利用Visual Studio提供的工具支持来简化WF应用程序的开发,例如使用设计器...

    C#与.NET.3.5高级程序设计(第4版)26-30章

    《C#与.NET.3.5高级程序设计(第4版)》的第26-30章涵盖了多个关键的.NET开发技术,包括Windows Workflow Foundation (WF),Windows Forms,以及Windows Presentation Foundation (WPF)的核心概念。以下是这些章节中的...

    一个基于C#实现的Getting started with the Workflow Foundation

    - C# 是 .NET 平台的主要开发语言,与 WF 集成方便,可用来编写工作流服务和宿主应用程序。 - 使用 C# 定义活动:通过继承自 System.Activities.Activity 类,可以创建自定义的活动组件。 3. **创建第一个工作流*...

    C#与.NET 3.5高级程序设计(第4版)(25-30).

    《C#与.NET 3.5高级程序设计(第4版)》是深入学习C#编程和.NET框架3.5版本的重要参考资料。本教材涵盖了多种关键技术和概念,旨在提升开发者在.NET平台上的专业技能。以下是根据提供的压缩包文件名解析出的几个关键...

    Workflow例子

    在学习WF时,理解基本概念如活动(Activity)、工作流定义(Workflow Definition)、执行宿主(Host)以及持久化(Persistence)是至关重要的。活动是WF的核心元素,代表了流程中的一个步骤或操作;工作流定义则是用...

    .net实现的工作流系统源码

    8. **宿主环境**: 工作流运行需要一个宿主环境,如ASP.NET应用程序、Windows服务或独立的控制台应用。宿主负责初始化工作流运行时,加载和执行工作流实例。 9. **活动库与复用**: 为了提高代码重用性,开发者可以...

    Visual C# 2010入门经典 英文原版电子书

    它通过一系列章节详细介绍了C#语言的基础知识和高级特性,旨在帮助读者快速掌握C#编程技巧,并能够独立开发基于.NET Framework的应用程序。 #### 二、C#语言基础 1. **C#简介** - C#是一种现代的、面向对象的编程...

Global site tag (gtag.js) - Google Analytics