工作流包装
来源:互联网 发布:淘宝双十一外围会场 编辑:程序博客网 时间:2024/05/17 01:33
工作流包装
1. 运行时包装
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Workflow.Runtime;
namespace Nocturne.Workflow.Hosting
{
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("需要一个非空的 WorkflowRuntime 实例"); }
// 提交所有的工作流事件
SubscribeToEvents(instance);
}
/// <summary>
/// 创建并启动一个工作流。
/// </summary>
/// <param name="workflowType">待启动的工作流类型</param>
/// <param name="parameters">入口参数</param>
/// <returns>包装在一个WorkflowInstanceWrapper里的工作流实例</returns>
public WorkflowInstanceWrapper StartWorkflow(Type workflowType, Dictionary<string, object> parameters)
{
WorkflowInstance instance = _workflowRuntime.CreateWorkflow(workflowType, parameters);
WorkflowInstanceWrapper wrapper = AddWorkflowInstance(instance);
instance.Start();
return wrapper;
}
#region 公共属性和事件
/// <summary>
/// 获取WorkflowRuntime实例
/// </summary>
public WorkflowRuntime WorkflowRuntime
{ get { return _workflowRuntime; } }
/// <summary>
/// 获取工作流实例包装的一个字典
/// </summary>
public Dictionary<Guid, WorkflowInstanceWrapper> Workflows
{ get { return _workflows; } }
/// <summary>
/// 记录该类的日志信息的事件
/// </summary>
public event EventHandler<WorkflowLogEventArgs> MessageEvent;
#endregion
#region 工作流集合管理
/// <summary>
/// 从工作流字典中移除某个实例
/// </summary>
/// <param name="workflowId"></param>
public void ClearWorkflow(Guid workflowId)
{ if (_workflows.ContainsKey(workflowId))
{ _workflows.Remove(workflowId); }
}
/// <summary>
/// 从字典中清除所有的工作流
/// </summary>
public void ClearAllWorkflows() {
_workflows.Clear();
}
/// <summary>
/// 向字典中添加一个新的工作流实例
/// </summary>
/// <param name="instance"></param>
/// <returns></returns>
private WorkflowInstanceWrapper AddWorkflowInstance(WorkflowInstance instance)
{ WorkflowInstanceWrapper wrapper = null;
if (!_workflows.ContainsKey(instance.InstanceId))
{ wrapper = new WorkflowInstanceWrapper(instance);
_workflows.Add(wrapper.Id, wrapper);
} return wrapper;
}
/// <summary>
/// 依据Guid查找工作流实例
/// </summary>
/// <param name="workflowId"></param>
/// <returns></returns>
public WorkflowInstanceWrapper FindWorkflowInstance(Guid workflowId)
{ WorkflowInstanceWrapper result = null;
if (_workflows.ContainsKey(workflowId))
{ result = _workflows[workflowId]; }
return result;
}
/// <summary>
/// 等待所有的工作流实例完成
/// </summary>
/// <param name="msecondsTimeout"></param>
public void WaitAll(int msecondsTimeout)
{
if (_workflows.Count > 0)
{
WaitHandle[] handles = new WaitHandle[_workflows.Count];
int index = 0;
foreach (WorkflowInstanceWrapper wrapper in _workflows.Values)
{
handles[index] = wrapper.WaitHandle;
index++;
}
WaitHandle.WaitAll(handles, msecondsTimeout, false);
}
}
#endregion
#region IDisposable Members
/// <summary>
/// 销毁工作流运行时
/// </summary>
public void Dispose()
{
if (_workflowRuntime != null)
{
_workflowRuntime.StopRuntime();
_workflowRuntime.Dispose();
}
ClearAllWorkflows();
}
#endregion
#region 工作流事件处理
/// <summary>
/// 订阅我们所有关心的事件
/// </summary>
/// <param name="runtime"></param>
private void SubscribeToEvents(WorkflowRuntime runtime)
{
runtime.Started += new EventHandler<WorkflowRuntimeEventArgs>(runtime_Started);
runtime.Stopped += new EventHandler<WorkflowRuntimeEventArgs>(runtime_Stopped);
runtime.WorkflowAborted += new EventHandler<WorkflowEventArgs>(runtime_WorkflowAborted);
runtime.WorkflowCompleted += new EventHandler<WorkflowCompletedEventArgs>(runtime_WorkflowCompleted);
runtime.WorkflowCreated += new EventHandler<WorkflowEventArgs>(runtime_WorkflowCreated);
runtime.WorkflowIdled += new EventHandler<WorkflowEventArgs>(runtime_WorkflowIdled);
runtime.WorkflowLoaded += new EventHandler<WorkflowEventArgs>(runtime_WorkflowLoaded);
runtime.WorkflowPersisted += new EventHandler<WorkflowEventArgs>(runtime_WorkflowPersisted);
runtime.WorkflowResumed += new EventHandler<WorkflowEventArgs>(runtime_WorkflowResumed);
runtime.WorkflowStarted += new EventHandler<WorkflowEventArgs>(runtime_WorkflowStarted);
runtime.WorkflowSuspended += new EventHandler<WorkflowSuspendedEventArgs>(runtime_WorkflowSuspended);
runtime.WorkflowTerminated += new EventHandler<WorkflowTerminatedEventArgs>(runtime_WorkflowTerminated);
runtime.WorkflowUnloaded += new EventHandler<WorkflowEventArgs>(runtime_WorkflowUnloaded);
}
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);
}
// 引发事件
MessageEvent(this, new WorkflowLogEventArgs(formattedMsg));
}
}
#endregion
}
/// <summary>
/// 在管理类中用来记录日志信息的EventArgs
/// </summary>
public class WorkflowLogEventArgs : EventArgs
{
private string _msg = string.Empty;
public WorkflowLogEventArgs(string msg)
{
_msg = msg;
}
public string Message
{ get { return _msg; } }
}
}
2. 工作流实例包装
using System;
using System.Collections.Generic;
using System.Threading;
using System.Workflow.Runtime;
namespace Nocturne.Workflow.Hosting
{
/// <summary>
/// 工作流实例的容器
/// </summary>
[Serializable]
public class WorkflowInstanceWrapper
{
private WorkflowInstance _workflowInstance;
private ManualResetEvent _waitHandle = new ManualResetEvent(false);
private Dictionary<string, object> _outputParameters = new Dictionary<string, object>();
private Exception _exception;
private string _reasonSuspended = string.Empty;
public WorkflowInstanceWrapper(WorkflowInstance instance)
{ _workflowInstance = instance; }
#region 公开属性与方法
/// <summary>
/// 获取工作流实例的 ID
/// </summary>
public Guid Id
{
get
{
if (_workflowInstance != null) { return _workflowInstance.InstanceId; }
else { return Guid.Empty; }
}
}
/// <summary>
/// 输出参数的集合
/// </summary>
public Dictionary<string, object> OutputParameters
{ get { return _outputParameters; } set { _outputParameters = value; } }
/// <summary>
/// 一个等待句柄。宿主应用程序可以使用它,挂起
/// 进程直到工作流完成。
/// </summary>
public ManualResetEvent WaitHandle
{ get { return _waitHandle; } set { _waitHandle = value; } }
/// <summary>
/// 工作流可能抛出的异常对象
/// </summary>
public Exception Exception
{ get { return _exception; } set { _exception = value; } }
/// <summary>
/// 工作流挂起的原因
/// /// </summary>
public string ReasonSuspended
{ get { return _reasonSuspended; } set { _reasonSuspended = value; } }
/// <summary>
/// 真实的工作流实例
/// </summary>
public WorkflowInstance WorkflowInstance
{ get { return _workflowInstance; } }
/// <summary>
/// 工作流完成的信号,宿主应用程序可以停止等待
/// </summary>
public void StopWaiting()
{
_waitHandle.Set();
}
#endregion
}
}
3. 测试程序
using System;
using System.Collections.Generic;
using System.Text;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
using Nocturne.Workflow.Hosting;
namespace ConsoleHostingManaged
{
/// <summary>
/// 使用自定义封装类来host工作流
/// </summary> class WorkflowTest
{
/// Run 方法将在 Main 方法启动之后被执行,该方法创建一个 WorkflowRuntimeManager 的实例而启动,
/// 使用 using 的目的在于一旦离开这个语句块,就可以自动调用 Dispose 方法来销毁对象,前面实现
/// IDisposable 接口的意义就在于此。
/// WorkflowRuntimeManager 构造函数被传入一个 WorkflowRuntime 类的实例。这就是我们设计管理类
/// 的目的,从外部构造 WorkflowRuntime,以此来提供附加的过占星。
/// 一个事件句柄被作为 WorkflowRuntimeManager.MessageEvent 添加。此事件在处理 WorkflowRuntime
/// 事件的时候会被出发。这段代码仅仅是简单的将信息输出到屏幕上
/// <summary>
/// 启动工作流
/// </summary>
public static void Run()
{
Console.WriteLine("使用 persistence 服务运行测试");
using (WorkflowRuntimeManager manager = new WorkflowRuntimeManager(new WorkflowRuntime()))
{
// 添加一个事件句柄记录日志
manager.MessageEvent += delegate(object sender, WorkflowLogEventArgs e){ Console.WriteLine(e.Message); }
// 创建完 WorkflowRuntime 及其包装之后,我们采用私有的 AddServices 方法向工作流运行
// 时添加服务。
AddServices(manager.WorkflowRuntime);
// 启动工作流运行时。注意这一步并非必须,如果忽略这条语句,工作流运行时同样会自动运
// 行。但是所有的核心服务必须在启动运行时引擎之前声明,如果我们在调用这条语句之后
// (或者被自动调用了)才添加核心服务(也就是上面那句话),编译器会抛出异常。
manager.WorkflowRuntime.StartRuntime();
// 当核心服务添加到运行时引擎之后,就可以运行工作流了。Dictionary 就是用来传送参数的
// 桥梁
Dictionary<string, object> wfArguments = new Dictionary<string, object>();
wfArguments.Add("InputString", "One");
manager.StartWorkflow(typeof(SharedWorkflows.Workflow1), wfArguments);
// 启动另一个实例。
wfArguments.Clear();
wfArguments.Add("InputString", "two");
manager.StartWorkflow(typeof(SharedWorkflows.Workflow1),wfArguments);
wfArguments.Clear();
wfArguments.Add("InputString","three");
manager.StartWorkflow(typeof(SharedWorkflows.Workflow1),wfArguments);
// 等待所有工作流实例完成
manager.WaitAll(15000);
// 显示所有工作流实例的结果。由于这些工作流是存储在Dictionary里的,因此可以
// 使用 foreach 进行迭代
foreach(WorkflowInstanceWrapper wrapper in manager.Workflows.Values)
{ if (wrapper.OutputParameters.ContainsKey("Result"))
{ Console.WriteLine(wrapper.OutputParameters["Result"]); }
else
{ if (wrapper.Exception!=null)
{ Console.WriteLine("{0} - 异常: {1}",wrapper.Id,wrapper.Exception.Message); } } }
manager.ClearAllWorkflows(); } }
/// <summary>
/// 添加运行时引擎需要的服务
/// </summary>
/// <param name="instance"></param>
private static void AddServices(WorkflowRuntime instance)
{
string connStringPersistence = string.Format("Initial Catalog={0}; Data Source={1}; Integrated Security={2};", "WorkflowPersistence", @"localhost/SQLEXPRESS", "SSPI");
instance.AddService(new SqlWorkflowPersistenceService(connStringPersistence, true, new TimeSpan(0, 2, 0), new TimeSpan(0, 0, 5)));
}
}
}
- 工作流包装
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- 工作流
- Wcf的简单使用
- 孔子论天命
- 『天涯杂谈』小说连载《考研江湖狼烟起,层层黑幕惊天地》
- CheckBoxList生成CheckBox并记录用户选择
- Struts配置文件详解
- 工作流包装
- 定制Mac OS X系统的准备(1)
- 如此销魂
- 构建自己的工作流平台
- 定制Mac OS X系统的准备(2)
- struts1.x 后台读取数据至html:select标签方法
- java学习笔记(二)
- 创业2年
- 精确获取时间(QueryPerformanceCounter)