我们之前写工作流宿主程序一般都是直接写在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
<string, object>();
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(this, new WorkflowLogEventArgs(formattedMsg));
}
}
}
public class WorkflowLogEventArgs : EventArgs
{
private String _msg = String.Empty;
public WorkflowLogEventArgs(String msg)
{
_msg = msg;
}
public String Message
{
get { return _msg; }
}
{
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(this, new 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<string, object>();
wfArguments.Add("InputString", "one");
WorkflowInstanceWrapper instance = manager.StartWorkflow(
typeof(SharedWorkflows.Workflow1), wfArguments);
instance.WorkflowInstance.Terminate("Manually terminated");
instance.WaitHandle.WaitOne(10000, false);
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();
下面运行结果,从该结果可以清晰的看出工作流的执行过程:
上一篇:坚持学习WF(5):自定义活动(CustomActivity)
下一篇:坚持学习WF(7):流程控制(Flow Control)
发表评论
-
平淡的2007
2007-12-24 08:04 817早上起来,送女朋友去公交车站,然后回来赶紧打开电脑,先 ... -
DreamSpark发布,高校学生免费使用Visual Studio 2008 Professional Edition 等微软软件
2008-02-20 13:23 1415今天上网无意中搜索到学生可以免费使用VS2008专业版,后来又 ... -
坚持学习WF(1):从HelloWorld开始
2008-04-04 16:30 892[置顶]坚持学习WF文章索 ... -
坚持学习WF(2):WF创作模式和设计时工具
2008-04-05 17:19 639[置顶]坚持学习WF文章索 ... -
坚持学习WF(3):WF框架概览
2008-04-08 07:27 783[置顶]坚持学习WF文章索 ... -
坚持学习WF(4):活动(Activity)和依赖属性(DependencyProperty)
2008-04-12 00:01 1148[置顶]坚持学习WF文章索引 活动(Activity) 活动 ... -
坚持学习WF(5):自定义活动(CustomActivity)
2008-04-13 15:25 929当WF提供的标准活动不能满足我们的需求的时候,我们就需要定义自 ... -
MOSS点滴(1):如何开发和部署feature
2008-04-16 21:35 836Features 是MOSS 2007以开箱即用的一套新功能, ... -
MOSS点滴(2):自定义Application Page
2008-04-19 20:07 845在MOSS中后台管理的页面都是Application Pag ... -
MOSS点滴(3):说说MOSS中的母版页
2008-04-25 21:15 1189MOSS中有两种页面:Site P ... -
MOSS点滴(4):实现Form认证
2008-04-29 21:12 705本文主要参考了网上的一些文章,但有些文章有些地方说的不是很明确 ... -
坚持学习WF(7):流程控制(Flow Control)
2008-04-30 18:10 839本文主要说说WF中和流 ... -
坚持学习WF(8):本地服务之调用外部方法
2008-05-09 08:17 761WF提供了一组核心服务 ... -
MOSS中的WebPart开发
2008-05-10 13:53 1060由于在asp.net1.1的时候asp.net中还没有webp ... -
坚持学习WF(9):本地服务之事件处理
2008-05-28 07:49 800[置顶]坚持学习WF文章索引 一:先来介绍两个活动 Even ... -
坚持学习WF(10):在工作流中使用关联
2008-06-01 13:03 692[置顶]坚持学习WF文章索 ... -
坚持学习WF(11):工作流通信与队列
2008-06-07 15:45 736[置顶]坚持学习WF文章索引 WF 提供的通信模型是构建于 ... -
MOSS中创建自定义内容类型
2008-06-12 20:23 1107一:简要介绍 某类内容 ... -
.NET中IDisposable接口的基本使用
2008-06-15 12:01 950首先来看MSDN中关于这个接口的说明: [ComVisible ... -
坚持学习WF(12):使用EventHandlingScopeActivity活动
2008-06-18 22:46 685[置顶]坚持学习WF文章索引 EventHandlingSco ...
相关推荐
坚持学习WF(6):开发可复用的宿主程序 主要实现两个类来对WorkflowInstance和WorkflowRuntime进行简单的封装。 坚持学习WF(7):流程控制(Flow Control) 主要说了WF中和流程相关的活动,主要包括以下这些活动:...
【开发可复用的宿主程序】在软件开发中,特别是在使用Windows Workflow Foundation (WF) 构建工作流应用时,提高代码复用性是非常重要的。传统的做法是将宿主程序直接编写在`Program.cs`文件中,但这限制了代码的...
坚持学习WF(6):开发可复用的宿主程序 主要实现两个类来对WorkflowInstance和WorkflowRuntime进行简单的封装。 坚持学习WF(7):流程控制(Flow Control) 主要说了WF中和流程相关的活动,主要包括以下这些活动:...
坚持学习WF(6):开发可复用的宿主程序 主要实现两个类来对WorkflowInstance和WorkflowRuntime进行简单的封装。 坚持学习WF(7):流程控制(Flow Control) 主要说了WF中和流程相关的活动,主要包括以下这些活动:...
"坚持学习WF(6)开发可复用的宿主程序"则涉及如何将工作流集成到实际应用中,讲解了宿主的概念和如何创建一个能够启动、管理和持久化工作流实例的应用程序。 "坚持学习WF(9)本地服务之事件处理"探讨了WF中的事件处理...
- **WF编程入门**:学习如何使用WF进行编程,包括安装必要的开发环境、编写第一个WF应用程序等。 - **Visual Studio工作流支持**:介绍如何利用Visual Studio提供的工具支持来简化WF应用程序的开发,例如使用设计器...
《C#与.NET.3.5高级程序设计(第4版)》的第26-30章涵盖了多个关键的.NET开发技术,包括Windows Workflow Foundation (WF),Windows Forms,以及Windows Presentation Foundation (WPF)的核心概念。以下是这些章节中的...
- C# 是 .NET 平台的主要开发语言,与 WF 集成方便,可用来编写工作流服务和宿主应用程序。 - 使用 C# 定义活动:通过继承自 System.Activities.Activity 类,可以创建自定义的活动组件。 3. **创建第一个工作流*...
《C#与.NET 3.5高级程序设计(第4版)》是深入学习C#编程和.NET框架3.5版本的重要参考资料。本教材涵盖了多种关键技术和概念,旨在提升开发者在.NET平台上的专业技能。以下是根据提供的压缩包文件名解析出的几个关键...
在学习WF时,理解基本概念如活动(Activity)、工作流定义(Workflow Definition)、执行宿主(Host)以及持久化(Persistence)是至关重要的。活动是WF的核心元素,代表了流程中的一个步骤或操作;工作流定义则是用...
8. **宿主环境**: 工作流运行需要一个宿主环境,如ASP.NET应用程序、Windows服务或独立的控制台应用。宿主负责初始化工作流运行时,加载和执行工作流实例。 9. **活动库与复用**: 为了提高代码重用性,开发者可以...
它通过一系列章节详细介绍了C#语言的基础知识和高级特性,旨在帮助读者快速掌握C#编程技巧,并能够独立开发基于.NET Framework的应用程序。 #### 二、C#语言基础 1. **C#简介** - C#是一种现代的、面向对象的编程...