WF消息队列的使用
工作流队列用于在宿主程序或工作流外部服务与工作流中的活动之间传递消息。WF本质论里面写的很含糊,通过下面的例子可以很好的理解工作流队列的使用。
例子主要功能是,一流程运行到ReadLine活动处,等待用户在控制台的输入,如果用户没有输入,则流程会钝化,有一个书签(其实就是对事件的处理方法)会加到工作流队列的QueueItemAvailable事件上。
下面首先看ReadLine这个活动,解释看注释。
using System;
using System.Workflow.ComponentModel;
using System.Workflow.Runtime;
namespace EssentialWF.Activities {
public class ReadLine : Activity {
private string text;
public string Text {
get { return this.text; }
}
protected override void Initialize(IServiceProvider provider) {
//活动初始化时就用活动名字创建,不用担心多个实例间的重名情况,因为消息队列是跟着流程实例走的
WorkflowQueuingService qService =(WorkflowQueuingService)provider.GetService(typeof(WorkflowQueuingService));
if (!qService.Exists(this.Name))
qService.CreateWorkflowQueue(this.Name, true);
}
protected override ActivityExecutionStatus Execute(ActivityExecutionContext context) {
WorkflowQueuingService qService = context.GetService<WorkflowQueuingService>();
//尝试执行获取用户输入,如果有用户输入,Dequeue方法就能获取的到
//并将活动的执行状态置为结束
WorkflowQueue queue = qService.GetWorkflowQueue(Name);
if (queue.Count > 0) {
this.text = (string)queue.Dequeue();
return ActivityExecutionStatus.Closed;
}
//尝试执行没有成功,给队列的QueueItemAvailable事件(此事件会在消息入队列时触发)加上处理方法
//并将活动的执行状态置为运行中
queue.QueueItemAvailable += this.ContinueAt;
return ActivityExecutionStatus.Executing;
}
//下面都很好理解了,不说了
void ContinueAt(object sender, QueueEventArgs e) {
ActivityExecutionContext context = sender as ActivityExecutionContext;
WorkflowQueuingService qService = context.GetService<WorkflowQueuingService>();
WorkflowQueue queue = qService.GetWorkflowQueue(Name);
this.text = (string)queue.Dequeue();
context.CloseActivity();
}
protected override void Uninitialize(IServiceProvider provider) {
WorkflowQueuingService qService = (WorkflowQueuingService)provider.GetService(typeof(WorkflowQueuingService));
if (qService.Exists(this.Name))
qService.DeleteWorkflowQueue(this.Name);
}
}
}
再看我们的宿主程序怎么和ReadLine活动配合。
string s = Console.ReadLine();
instance.EnqueueItem(“rl1”,s,null,null);//这行代码就是向队列中加入消息,rl1是活动的名称,s是消息的数据信息,后两个参数是用于传递消息后接受反馈的通知。