中断工作流并持久化到数据库中
中断工作流并持久化到数据库中
工作流图如下:
说明:工作流中的行为为自定义行为。该工作流的执行流程如下:张三,李四与王五三个审核稿件,三个人必须通过才通过,如果不通过则继续审核,直到通过为止。
如果不通过,则将数据持久化到数据库中,并中断工作流的执行。可以通过加载工作流再次执行工作流。
自定义的审核行为代码如下:
[PersistOnClose()]// 必须有该属性,该属性是表示在执行该行为结束后持久化工作流
public partial class AuditingActivity: Activity
{
public AuditingActivity()
{
InitializeComponent();
}
/// <summary>
/// 自定义UserName(用户名)属性
/// </summary>
public static DependencyProperty UserNameProperty = DependencyProperty.Register("UserName", typeof(string), typeof(AuditingActivity));
public string UserName
{
get
{
return (string)base.GetValue(AuditingActivity.UserNameProperty);
}
set
{
base.SetValue(AuditingActivity.UserNameProperty, value);
}
}
/// <summary>
/// 重写行为的执行方法
/// </summary>
/// <param name="executionContext"></param>
/// <returns></returns>
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
Console.Write("{0}用户审核结果: ", UserName);
if (Console.ReadLine().ToLower() == "true")
{
Console.WriteLine("{0}用户审核通过", UserName);
}
else
{
Console.WriteLine("{0}用户审核不通过", UserName);
// 进入空闲状态。在空闲状态中中断工作流。
// 不能在行为内部调用WorkflowInstance.Abort()等方法。
return ActivityExecutionStatus.Executing;
}
return ActivityExecutionStatus.Closed;
}
}
public partial class AuditingActivity: Activity
{
public AuditingActivity()
{
InitializeComponent();
}
/// <summary>
/// 自定义UserName(用户名)属性
/// </summary>
public static DependencyProperty UserNameProperty = DependencyProperty.Register("UserName", typeof(string), typeof(AuditingActivity));
public string UserName
{
get
{
return (string)base.GetValue(AuditingActivity.UserNameProperty);
}
set
{
base.SetValue(AuditingActivity.UserNameProperty, value);
}
}
/// <summary>
/// 重写行为的执行方法
/// </summary>
/// <param name="executionContext"></param>
/// <returns></returns>
protected override ActivityExecutionStatus Execute(ActivityExecutionContext executionContext)
{
Console.Write("{0}用户审核结果: ", UserName);
if (Console.ReadLine().ToLower() == "true")
{
Console.WriteLine("{0}用户审核通过", UserName);
}
else
{
Console.WriteLine("{0}用户审核不通过", UserName);
// 进入空闲状态。在空闲状态中中断工作流。
// 不能在行为内部调用WorkflowInstance.Abort()等方法。
return ActivityExecutionStatus.Executing;
}
return ActivityExecutionStatus.Closed;
}
}
工作流运行时引擎代码如下:
/// <summary>
/// 工作流运行时引擎类
/// </summary>
public class Runtime:IDisposable
{
WorkflowRuntime workflowRuntime = null;
ManualWorkflowSchedulerService manualWorkflowSchedulerService = null;
/// <summary>
/// 初始化工作流引擎的服务与事件,并运行工作流引擎
/// </summary>
public Runtime()
{
workflowRuntime = new WorkflowRuntime();
// 需要将SqlWorkflowPersistenceService服务的unloadOnIdle参数设置为false表示不让工作流在空闲或卸载时自动持久化。
// 如果设置为true,将会在unload()执行后自动持久化工作流,这将导致无法正常加载工作流。
workflowRuntime.AddService(new SqlWorkflowPersistenceService("server=(local);database=AuditingWorkflow;integrated security=sspi", false, new TimeSpan(0, 0, 5), new TimeSpan(0, 0, 10)));
// 添加手动调度服务
manualWorkflowSchedulerService = new ManualWorkflowSchedulerService();
workflowRuntime.AddService(manualWorkflowSchedulerService);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
{
Console.WriteLine("{0}工作流结束", e.WorkflowInstance.InstanceId);
};
workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine("{0}工作流终止", e.WorkflowInstance.InstanceId);
};
workflowRuntime.WorkflowIdled += delegate(object sender, WorkflowEventArgs e)
{
e.WorkflowInstance.Abort();
Console.WriteLine("中断了{0}工作流", e.WorkflowInstance.InstanceId);
};
workflowRuntime.WorkflowPersisted += new EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowPersisted);
workflowRuntime.StartRuntime();
}
void workflowRuntime_WorkflowPersisted(object sender, WorkflowEventArgs e)
{
Console.WriteLine("{0}工作流持久化",e.WorkflowInstance.InstanceId);
}
/// <summary>
/// 获取工作流调度
/// </summary>
public ManualWorkflowSchedulerService WorkflowScheduler
{
get
{
return manualWorkflowSchedulerService;
}
}
/// <summary>
/// 通过工作流类型创建工作流的实例
/// </summary>
/// <param name="workflowType"></param>
/// <returns></returns>
public Guid CreateWorkflow(Type workflowType)
{
WorkflowInstance instance = workflowRuntime.CreateWorkflow(workflowType);
Console.WriteLine("创建了{0}工作流", instance.InstanceId);
// 先将工作流开始,再将工作流卸载,这个顺序不能变动。否则将在创建的时候就运行了工作流并且如果第一个审核行为不通过,就不能正常加载了
instance.Start();
instance.Unload();
// 必须执行该语句,否则无法正常加载工作流,具体原因还不太清楚,跟踪工作流的时候,有没有执行该语句的工作流执行状态是一样的
// 初步分析是因为执行Start()方法并没有真正的执行工作流(因为该引擎用了ManualWorkflowSchedulerService服务),直到调用RunWorkflow()方法时才执行工作流
manualWorkflowSchedulerService.RunWorkflow(instance.InstanceId);
return instance.InstanceId;
}
/// <summary>
/// 通过工作流ID加载工作流
/// </summary>
/// <param name="workflowGuid"></param>
public void LoadWorkflow(Guid workflowGuid)
{
// 通过工作流ID获取工作流实例
WorkflowInstance instance = workflowRuntime.GetWorkflow(workflowGuid);
if (instance == null)
return;
// 加载工作流
instance.Load();
// 通过调度服务运行工作流
manualWorkflowSchedulerService.RunWorkflow(instance.InstanceId);
}
/// <summary>
/// 资源清理
/// </summary>
public void Dispose()
{
if (workflowRuntime != null)
workflowRuntime.Dispose();
}
}
/// 工作流运行时引擎类
/// </summary>
public class Runtime:IDisposable
{
WorkflowRuntime workflowRuntime = null;
ManualWorkflowSchedulerService manualWorkflowSchedulerService = null;
/// <summary>
/// 初始化工作流引擎的服务与事件,并运行工作流引擎
/// </summary>
public Runtime()
{
workflowRuntime = new WorkflowRuntime();
// 需要将SqlWorkflowPersistenceService服务的unloadOnIdle参数设置为false表示不让工作流在空闲或卸载时自动持久化。
// 如果设置为true,将会在unload()执行后自动持久化工作流,这将导致无法正常加载工作流。
workflowRuntime.AddService(new SqlWorkflowPersistenceService("server=(local);database=AuditingWorkflow;integrated security=sspi", false, new TimeSpan(0, 0, 5), new TimeSpan(0, 0, 10)));
// 添加手动调度服务
manualWorkflowSchedulerService = new ManualWorkflowSchedulerService();
workflowRuntime.AddService(manualWorkflowSchedulerService);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e)
{
Console.WriteLine("{0}工作流结束", e.WorkflowInstance.InstanceId);
};
workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine("{0}工作流终止", e.WorkflowInstance.InstanceId);
};
workflowRuntime.WorkflowIdled += delegate(object sender, WorkflowEventArgs e)
{
e.WorkflowInstance.Abort();
Console.WriteLine("中断了{0}工作流", e.WorkflowInstance.InstanceId);
};
workflowRuntime.WorkflowPersisted += new EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowPersisted);
workflowRuntime.StartRuntime();
}
void workflowRuntime_WorkflowPersisted(object sender, WorkflowEventArgs e)
{
Console.WriteLine("{0}工作流持久化",e.WorkflowInstance.InstanceId);
}
/// <summary>
/// 获取工作流调度
/// </summary>
public ManualWorkflowSchedulerService WorkflowScheduler
{
get
{
return manualWorkflowSchedulerService;
}
}
/// <summary>
/// 通过工作流类型创建工作流的实例
/// </summary>
/// <param name="workflowType"></param>
/// <returns></returns>
public Guid CreateWorkflow(Type workflowType)
{
WorkflowInstance instance = workflowRuntime.CreateWorkflow(workflowType);
Console.WriteLine("创建了{0}工作流", instance.InstanceId);
// 先将工作流开始,再将工作流卸载,这个顺序不能变动。否则将在创建的时候就运行了工作流并且如果第一个审核行为不通过,就不能正常加载了
instance.Start();
instance.Unload();
// 必须执行该语句,否则无法正常加载工作流,具体原因还不太清楚,跟踪工作流的时候,有没有执行该语句的工作流执行状态是一样的
// 初步分析是因为执行Start()方法并没有真正的执行工作流(因为该引擎用了ManualWorkflowSchedulerService服务),直到调用RunWorkflow()方法时才执行工作流
manualWorkflowSchedulerService.RunWorkflow(instance.InstanceId);
return instance.InstanceId;
}
/// <summary>
/// 通过工作流ID加载工作流
/// </summary>
/// <param name="workflowGuid"></param>
public void LoadWorkflow(Guid workflowGuid)
{
// 通过工作流ID获取工作流实例
WorkflowInstance instance = workflowRuntime.GetWorkflow(workflowGuid);
if (instance == null)
return;
// 加载工作流
instance.Load();
// 通过调度服务运行工作流
manualWorkflowSchedulerService.RunWorkflow(instance.InstanceId);
}
/// <summary>
/// 资源清理
/// </summary>
public void Dispose()
{
if (workflowRuntime != null)
workflowRuntime.Dispose();
}
}
客户端代码如下:
class Program
{
static void Main(string[] args)
{
// 实例化工作流运行时引擎,该类的实例最好在系统初始化时实例化,在系统结束后执行Dispose()方法
Runtime runtime = new Runtime();
string input = null;
Console.Write("请输入命令: ");
while ((input = Console.ReadLine().ToLower()) != "end")
{
switch (input)
{
case "create": // 创建工作流
runtime.CreateWorkflow(typeof(BreakWorkflowAndPersistenceToDatabase.AuditingWorkflow));
break;
case "load": // 通过工作流ID加载工作流
Console.Write("请输入工作流ID: ");
try
{
Guid guid = new Guid(Console.ReadLine());
runtime.LoadWorkflow(guid);
}
catch (Exception ex)
{
Console.WriteLine("加载工作流出错!原因:{0}", ex.Message);
}
break;
}
Console.Write("请输入命令: ");
}
}
}
{
static void Main(string[] args)
{
// 实例化工作流运行时引擎,该类的实例最好在系统初始化时实例化,在系统结束后执行Dispose()方法
Runtime runtime = new Runtime();
string input = null;
Console.Write("请输入命令: ");
while ((input = Console.ReadLine().ToLower()) != "end")
{
switch (input)
{
case "create": // 创建工作流
runtime.CreateWorkflow(typeof(BreakWorkflowAndPersistenceToDatabase.AuditingWorkflow));
break;
case "load": // 通过工作流ID加载工作流
Console.Write("请输入工作流ID: ");
try
{
Guid guid = new Guid(Console.ReadLine());
runtime.LoadWorkflow(guid);
}
catch (Exception ex)
{
Console.WriteLine("加载工作流出错!原因:{0}", ex.Message);
}
break;
}
Console.Write("请输入命令: ");
}
}
}
执行结果如下:
注意:在输入命令的时候要快,不然会失效,可能原因是因为工作流的行为在运行过程中有运行时间控制,如果在某个时间内工作流行为(activity)处于不执行状态则中止工作流执行。也可能因为线程的切换导致的。目前我还没有分析出具体原因。望高手们能够帮忙找出原因。