WorkflowRuntime简介
在Windows Workflow中,活动可以视作提交给工作流处理器执行的指令或代码,而这个工作流处理器就是WorkflowRuntime。为了启动工作流,我们必须托管WorkflowRuntime与工作流服务。
Windows Workflow不是单独的应用程序,它和ASP.NET类似, Workflow生存在程序集中(比如System.Workflow.Runtime.dll)。Workflow需要一个用以载入,初始化并启动工作流的Runtime宿主进程.和ASP.NET不同的是WF的宿主并不是唯一的,我们可以将WF托管在智能客户端应用程序,控制台应用程序或者Windows服务的进程中。
要想使工作流执行环境运作起来只需创建一个WorkflowRuntime类的实例并调用StartRuntime方法即可.WorkflowRuntime定义了允许定制执行环境的方法和可以在执行期间监听的事件.当工作流完成了执行,中断或者空闲时Runtime便会触发事件.
只要创建了Runtime的实例,我们就可以使用CreateWorkflow方法创建工作流,CreateWorkflow方法返回一个WorkflowInstance对象,WorkflowInstance类用来表示一个工作流.工作流实例的Start方法将开始工作流的执行.如果发生了异常,工作流便调用Terminate方法(会导致Runtime抛出WorkflowTerminated事件),调用顺序如下图所示.
综上所述,WorkflowRuntime和WorkflowInstance类是工作流运行时最重要的两个类,除了这两个必需的类之外,还有其它内置在WF程序集中的类也在为WF Runtime提供许多重要的服务.
Runtime 服务
WorkflowRuntime类仅仅提供了执行工作流的基本功能,之前我们提到的一些重要功能(比如跟踪工作流)则可以通过WorkflowRuntime提供的扩展性机制-AddService方法来实现.
AddService允许我们向Runtime中添加可用的服务.这些服务可以是我们为特定领域编写的自定义服务,也可以是WF中内置的服务.
调度服务 Scheduling Services
调度服务用来控制Runtime执行工作流所需要的线程.
DefaultWorkflowSchedulerService会创建新的线程来执行工作流.因为工作流和宿主应用程序的线程是分开的,所以工作流是异步执行的并且不会阻止任何应用程序的线程.我们还可以配置允许同时执行的工作流最大数量.
当宿主应用程序可以转让线程给工作流Runtime时可以使用另外一个调度服务ManualWorkflowSchedulerService.对服务器端应用程序(比如ASP.NET Web应用程序和Web Service)而言,把线程转让给Runtime非常有用.服务器端应用程序通常的做法是为每个客户端请求的服务创建线程.而宿主应用程序把线程”借给”WF Runtime的意义在于可以让Runtime在每个请求的线程上同步地执行工作流,而不是为每个请求创建两个线程.
和Windows Worklow的所有服务一样,如果内置的服务不能满足你的需求,你可以定义你自己的调度服务.
事务服务 Transaction Services
事务服务允许Runtime保持位于工作流内部和持久存储器(durable store)中的状态的一致性.默认的事务服务是DefaultWorkflowTransactionService类的实例.正在运行的工作流进程中的活动和此服务共享相同的进程和相同的事务上下文.
WF依靠.NET中的System.Transactions名称空间来实现事务机制. Transactions类提供一个轻量级的, auto-enlisting并且可提升的事务.事务像本地事务一样启动,然后Runtime可以根据需要把它提升为重量级的分布式事务.
持久化服务 Persistence Services
持久化服务负责把工作流状态保存到持久储存器.SqlWorkflowPersistenceService会把工作流状态保存到SQL Server数据库.长时间运行的工作流需要持久化服务,因为我们不能让处理订货单的工作流在内存里驻留30天直到客户支付才从内存中卸载.相反,Runtime应该保持工作流的状态到持久存储器中,并且把工作流实例从内存中卸载.在这30天中,Runtime可以重新加载工作流实例并恢复运行.当持久化服务启用时,WF Runtime会自动保持工作流空闲或者暂停等状态.
SqlWorkflowPersistenceService支持SQL Server 2000以及更高版本(还包括免费的MSDE和Express版).
跟踪服务 Tracking Services
当调度服务选择了工作流运行的线程之后,跟踪服务就会负责监视并记录工作流的执行信息.跟踪服务使用Tracking Profile来通知Runtime它需要的工作流信息的类型.跟踪服务还可以打开跟踪频道(Tracking Channel)来接收事件和数据.
WF包含一个SqlTrackingService类,这个类可以将跟踪数据存储到SQL Server数据库.跟踪服务将使用之前介绍过的事务服务来确保工作流的跟踪数据与被跟踪工作流的状态一致.默认Runtime不会启动跟踪服务,但我们可以用编程的方式添加跟踪服务(或使用应用程序配置文件配置跟踪服务)
WorkflowRuntime使用
/// <summary>
/// 工作流辅助类。
/// </summary>
public class WorkflowRunTimeUtil
{
#region 私有字段
/// <summary>
/// 工作流运行时。
/// </summary>
private static WorkflowRuntime _workflowRuntime = null;
/// <summary>
/// 持久化到文件系统的服务。
/// </summary>
private static FilePersistenceService _filePersistenceService = null;
/// <summary>
/// 持久化到Sql数据库的服务。
/// </summary>
private static SqlPersistenceService _sqlPersistenceService = null;
/// <summary>
/// 线程锁。
/// </summary>
private static object _syncRoot = new object();
/// <summary>
/// 定义Charge服务类,用来和工作流实例通讯
/// </summary>
private static Charge _chargeService = default(Charge);
/// <summary>
/// 定义扩展服务对象用来加载Charge服务类,并被工作流引擎加载
/// </summary>
private static ExternalDataExchangeService _dataExchangeService = default(ExternalDataExchangeService);
#endregion
#region 私有属性
/// <summary>
/// 工作流运行时。
/// </summary>
private static WorkflowRuntime WorkflowRuntimeManage
{
get
{
//多线程环境下防止并发访问
lock (_syncRoot)
{
if (_workflowRuntime == null)
{
//实例化工作流运行时。
_workflowRuntime = new WorkflowRuntime();
//定义工作流运行时事件触发的方法。
_workflowRuntime.WorkflowCompleted += OnWorkflowCompleted;
_workflowRuntime.WorkflowIdled += OnWorkflowIdled;
_workflowRuntime.WorkflowPersisted += OnWorkflowPersisted;
_workflowRuntime.WorkflowUnloaded += OnWorkflowUnloaded;
_workflowRuntime.WorkflowLoaded += OnWorkflowLoaded;
_workflowRuntime.WorkflowTerminated += OnWorkflowTerminated;
_workflowRuntime.WorkflowAborted += OnWorkflowAborted;
}
//加载持久化服务。
//if (_workflowRuntime.GetService<FilePersistenceService>() == null)
// _workflowRuntime.AddService(FilePersistenceService);
if (_workflowRuntime.GetService<SqlPersistenceService>() == null)
_workflowRuntime.AddService(SqlPersistenceService);
//加载扩展服务。
if (_workflowRuntime.GetService(DataExchangeService.GetType()) == null)
{
_workflowRuntime.AddService(DataExchangeService);
//加载自定义服务。
if (DataExchangeService.GetService(ChargeService.GetType()) == null)
DataExchangeService.AddService(ChargeService);
}
// 启动引擎
if (!_workflowRuntime.IsStarted)
_workflowRuntime.StartRuntime();
}
return _workflowRuntime;
//return GetWorkflowRuntime(WorkflowPersistenceServiceType.File);
}
}
/// <summary>
/// 持久化到文件系统的服务。
/// </summary>
private static FilePersistenceService FilePersistenceService
{
get
{
if (_filePersistenceService == null)
_filePersistenceService = new FilePersistenceService(GetFilePath(), true);
return _filePersistenceService;
}
}
/// <summary>
/// 持久化到Sql数据库的服务。
/// </summary>
private static SqlPersistenceService SqlPersistenceService
{
get
{
if (_sqlPersistenceService == null)
_sqlPersistenceService = new SqlPersistenceService(false);
return _sqlPersistenceService;
}
}
/// <summary>
/// 定义Charge服务类,用来和工作流实例通讯
/// </summary>
private static Charge ChargeService
{
get
{
if (_chargeService == null)
_chargeService = new Charge();
return _chargeService;
}
}
/// <summary>
/// 定义扩展服务对象用来加载Charge服务类,并被工作流引擎加载
/// </summary>
private static ExternalDataExchangeService DataExchangeService
{
get
{
if (_dataExchangeService == null)
_dataExchangeService = new ExternalDataExchangeService();
return _dataExchangeService;
}
}
#endregion
#region 私有方法
/// <summary>
/// 获取持久化到文件系统的路径。
/// </summary>
/// <returns></returns>
private static string GetFilePath()
{
return HttpContext.Current.Server.MapPath(ConfigUtil.GetAppSettingValue("WorkFlowFilePath"));
}
/// <summary>
/// 获取需要传送的ExternalDataEventArgs。
/// </summary>
/// <param name="instanceID"></param>
/// <returns></returns>
private static MyWorkFlowExtendEventArgs GetEvent(Guid instanceID)
{
MyWorkFlowExtendEventArgs e = new MyWorkFlowExtendEventArgs(instanceID);
e.WaitForIdle = true;
return e;
}
/// <summary>
/// 在终止工作流实例时发生。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnWorkflowTerminated(object sender, WorkflowTerminatedEventArgs e)
{
}
/// <summary>
/// 将工作流实例加载到内存时发生。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnWorkflowLoaded(object sender, WorkflowEventArgs e)
{
}
/// <summary>
/// 从内存卸载工作流实例时发生。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnWorkflowUnloaded(object sender, WorkflowEventArgs e)
{
}
/// <summary>
/// 在保留工作流的状态时发生。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnWorkflowPersisted(object sender, WorkflowEventArgs e)
{
}
/// <summary>
/// 在工作流实例进入空闲状态后发生。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnWorkflowIdled(object sender, WorkflowEventArgs e)
{
// 调用WorkflowPersistenceService进行持久化
e.WorkflowInstance.TryUnload();
}
/// <summary>
/// 在完成工作流实例时发生。
/// </summary>
/// <param name="sender"></param>
/// <param name="instance"></param>
static void OnWorkflowCompleted(object sender, WorkflowCompletedEventArgs instance)
{
IWorkFlowExampleManage workFlowExampleManager = BL.ServiceProvider.GetService<IWorkFlowExampleManage>();
WorkFlowExampleInfo info = workFlowExampleManager.Get(instance.WorkflowInstance.InstanceId);
info.IsCompleted = Convert.ToInt32(EIsFlag.Yes);
workFlowExampleManager.Save(info);
}
/// <summary>
/// 在中止工作流实例时发生。
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
static void OnWorkflowAborted(object sender, WorkflowEventArgs e)
{
}
/// <summary>
/// 保存工作流实例。
/// </summary>
/// <param name="prmExampleID">实例标识。</param>
/// <param name="name">名称。</param>
/// <param name="url">界面路径。</param>
/// <param name="description">描述。</param>
static void SaveWorkFlowExample(Guid prmExampleID, string name, string description,string url)
{
IWorkFlowExampleManage workFlowExampleManager = BL.ServiceProvider.GetService<IWorkFlowExampleManage>();
WorkFlowExampleInfo info = workFlowExampleManager.Get(prmExampleID);
if (info == null)
{
info = new WorkFlowExampleInfo();
info.ExampleID = prmExampleID;
info.IsCompleted = Convert.ToInt32(EIsFlag.No);
info.IsUnlock = Convert.ToInt32(EIsFlag.No);
}
info.Name = name;
info.Description = description;
info.Url = url;
workFlowExampleManager.Save(info);
}
#endregion
#region 公共方法
/// <summary>
/// 创建工作流。
/// </summary>
/// <param name="prmDefinitionID">工作流定义标识。</param>
public static Guid CreateWorkflow(WorkFlowDefinitionInfo definitionInfo, Dictionary<string, object> prmNamedArgumentValues)
{
if (definitionInfo == null)
throw new CustomException("该工作流不存在或已经被删除!", EExceptionType.Suggestive);
Dictionary<string, object> namedArgumentValues = prmNamedArgumentValues;
//创建工作流实例。
WorkflowInstance instance = WorkflowRuntimeManage.CreateWorkflow(WorkflowUtil.GetXmlReader(definitionInfo.WorkflowDefinition), WorkflowUtil.GetXmlReader(definitionInfo.Rules), namedArgumentValues);
//启动工作流。
instance.Start();
//
return instance.InstanceId;
}
/// <summary>
/// 创建工作流。
/// </summary>
/// <param name="prmDefinitionID">工作流定义标识。</param>
public static Guid CreateWorkflow(WorkFlowDefinitionInfo definitionInfo, Dictionary<string, object> prmNamedArgumentValues, string name, string description, string url)
{
if (definitionInfo == null)
throw new CustomException("该工作流不存在或已经被删除!", EExceptionType.Suggestive);
//创建工作流实例。
WorkflowInstance instance = WorkflowRuntimeManage.CreateWorkflow(WorkflowUtil.GetXmlReader(definitionInfo.WorkflowDefinition), WorkflowUtil.GetXmlReader(definitionInfo.Rules), prmNamedArgumentValues);
//保存实例。
SaveWorkFlowExample(instance.InstanceId, name, description, url);
//启动工作流。
instance.Start();
//
return instance.InstanceId;
}
/// <summary>
/// 加载并处理工作流。
/// </summary>
/// <param name="prmExampleID">工作流实例标识。</param>
/// <param name="isDispose">是否触发事件。</param>
/// <param name="id">事件ID。</param>
/// <returns>当前状态。</returns>
public static StateActivity LoadWorkflow(Guid prmExampleID, bool isDispose,string id)
{
WorkflowInstance instance = WorkflowRuntimeManage.GetWorkflow(prmExampleID);
if (isDispose)
{
WorkFlowChargeEventmanage.Extend(ChargeService, id, GetEvent(instance.InstanceId));
}
StateMachineWorkflowInstance stateMachine = new StateMachineWorkflowInstance(WorkflowRuntimeManage, instance.InstanceId);
return stateMachine.CurrentState;
}
/// <summary>
/// 获取工作流实例当前状态事件名称集合。
/// </summary>
/// <param name="prmExampleID">实例标识。</param>
/// <returns>键表示要触发的事件名称,值表示事件的描述。</returns>
public static IDictionary<string, string> GetEventNames(Guid prmExampleID)
{
IDictionary<string, string> eventNames = new Dictionary<string, string>();
//获取工作流实例。
WorkflowInstance instance = WorkflowRuntimeManage.GetWorkflow(prmExampleID);
StateMachineWorkflowInstance stateMachine = new StateMachineWorkflowInstance(WorkflowRuntimeManage, instance.InstanceId);
//当前状态可用的活动。
ReadOnlyCollection<Activity> activitys = stateMachine.CurrentState.EnabledActivities;
foreach (Activity itemInfo in activitys)
{
//判断多动是否是EventDrivenActivity。
if (itemInfo is EventDrivenActivity)
{
EventDrivenActivity edact = (EventDrivenActivity)itemInfo;
//判断子活动中第一个活动是否是HandleExternalEventActivity。
if (edact.EnabledActivities.Count > 0 && edact.EnabledActivities[0] is HandleExternalEventActivity)
{
HandleExternalEventActivity handle = edact.EnabledActivities[0] as HandleExternalEventActivity;
eventNames.Add(handle.EventName,handle.Description);
}
}
}
return eventNames;
}
/// <summary>
/// 持久化工作流。
/// </summary>
/// <param name="prmExampleID">实例标识。</param>
public static void Persistence(Guid prmExampleID)
{
WorkflowInstance instance = WorkflowRuntimeManage.GetWorkflow(prmExampleID);
instance.TryUnload();
}
#endregion
}