前言
工作流的启动都需要一个宿主,怎么理解呢,可以说工作流是虚拟存在,需要一个对象来承接,通过对象对工作流进行管理,于是就有了工作流宿主。工作流的宿主有多种,最常用的是三种,分别为WorkflowInvoker、WorkflowApplication和WorkflowServiceHost,其中前两种是最常用的宿主。本篇文章主要对前两个宿主进行介绍。
WorkflowInvoker
WorkflowInvoker提供调用工作流的简单方法,就像方法调用一样,但是只能用于不使用持久化的工作流,因为该对象不支持工作流的持久化。WorkflowInvoker调用工作流时,使用Invoke方法,传入要调用工作流的工作流定义,就可以启动工作流。
构造函数
WorkflowInvoker的构造函数为WorkflowInvoker,用来初始化WorkflowInvoker类的新实例。
属性
WorkflowInvoker有一个属性Extensions,获取对WorkflowInvoker实例调用的工作流可用的扩展的Collection<T>。
方法
WorkflowInvoker的方法有很多,在这里就不一一列举了。最常用的就是Invoke(Activity),将工作流定义传入方法中,就可以启动工作流,代码如下:
static void Main(string[] args)
{
//实例化工作流
Activity workflow1 = new Workflow1();
//使用WorkflowInvoker管理工作流
WorkflowInvoker.Invoke(workflow1);
WorkflowInvoker.Invoke(workflow1);
Console.ReadKey();
}
InvokeCompleted是WorkflowInvoker的一个事件,是在完成或取消有一种InvokeAsync()重载调用的工作流时发生的。
WorkflowApplication
WorkflowApplication为执行工作流提供更丰富的模型,包括生命周期事件通知、执行控制、书签恢复和持久性。其中书签恢复和持久性,弥补了WorkflowInvoker不能持久化的弊端。
构造函数
名称 | 说明 |
使用指定的工作流定义创建 WorkflowApplication 类的新实例。 | |
创建 WorkflowApplication 类的新实例,该实例使用指定的工作流定义和参数值。 | |
WorkflowApplication(Activity, IDictionary<String, Object>, WorkflowIdentity) | 使用指定的工作流定义、参数值以及定义标识创建WorkflowApplication 类的新实例。 |
使用指定的工作流定义和定义标识创建 WorkflowApplication 类的新实例。 |
属性
名称 | 说明 |
获取或设置中止工作流实例时调用的 Action<T>。 | |
获取或设置工作流实例完成时调用的 Action<T>。 | |
获取或设置 WorkflowInstance 的定义标识。(从 WorkflowInstance 继承。) | |
获取当前工作流实例的扩展的集合。 | |
获取或设置工作流实例的参数和变量的根环境。(从 WorkflowInstance 继承。) | |
获取当前工作流应用程序实例的 128 位 GUID 标识符。(替代 WorkflowInstance.Id。) | |
获取或设置当前工作流实例进入空闲状态时调用的 Action<T>。 | |
获取或设置一个对象,该对象提供对工作流应用程序的当前实例保留状态的访问。 | |
获取或设置当前工作流实例遇到未处理的异常时调用的 Func<T, TResult>。 | |
获取或设置当前工作流实例处于空闲状态并可被保留时调用的 T:System.Activities.ActivityFunc。 | |
获取一个值,该值指示宿主是否支持 P:System.Runtime.Persistence.InstanceView.InstanceKeys 与运行时实例的关联。(从 WorkflowInstance 继承。) | |
获取或设置用于调度工作流实例的 SynchronizationContext。(从 WorkflowInstance 继承。) | |
获取或设置卸载当前工作流时调用的 Action<T>。 | |
获取工作流实例的工作流定义。(从 WorkflowInstance 继承。) |
方法
WorkflowApplication的方法同样有很多,例如终止工作流的Abort()方法,取消工作流实例的Cancel()方法,加载指定的工作流的Load(Guid)方法,开始或回复执行工作流实例的Run()方法,保留或卸载工作流实例的Unload()方法。另外,相同的方法传入不同参数,又可以对工作流产生多种操作。
在工作流最初启动时,经常用的方法是Run(),利用WorkflowApplication的构造函数实例化要启动的工作流,然后利用Run()方法让工作流启动,代码如下:
static void Main(string[] args)
{
//Activity workflow1 = new Workflow1();
//WorkflowInvoker.Invoke(workflow1);
WorkflowApplication instance1 = new WorkflowApplication(new Workflow1());
WorkflowApplication instance2 = new WorkflowApplication(new Workflow1());
instance1.Run();
instance2.Run();
Console.ReadKey();
}
作用
1、创建新的工作流实例,或从实例存储区中加载工作流实例
2、提供扩展以供工作流实例内的活动使用
3、提供工作流实例的执行
4、恢复由工作流实例内的活动创建的书签
5、保留或卸载工作流实例
6、接收工作流实例生命周期事件通知
两者的异同
相同点
1、都能够作为工作流的宿主,对工作流进行各种操作。
2、都有相应的操作工作流的方法。
3、公共成员是线程安全的,但不保证所有实例成员都是线程安全的。
不同点
1、持久化的能力不同
WorkflowInvoker不支持工作流的持久化,因为它没有提供相应的方法,但是WorkflowApplication可以进行工作流的持久化。
WorkflowApplication对象的Load(Guid)方法就是支持持久化的体现,因为它是从数据库中通过唯一性标识Guid来获取工作流实例,这样就可以保证实例的唯一性。只要有实例的Guid,就可以在数据库中获得当前实例。而WorkflowInvoker没有相关方法。
2、启动实例时,实例在宿主中的线程是不同的。
使用WorkflowInvoker启动工作流时,工作流将附加到宿主的线程中执行。而WorkflowApplication则不同,它是将工作流实例放在宿主线程之外的另一线程中,利用线程池进行管理。
现在有一个实例,创建一个工作流控制台应用程序,添加一个代码活动,该类的作用是每个半秒打印一个数字,数字为1-10,然后分别用不同宿主启动工作流,执行的效果不同。
实例参考:http://www.cnblogs.com/foundation/category/215023.html
代码活动中的代码:
public sealed class runtimeTestActivity : CodeActivity
{
protected override void Execute(CodeActivityContext context)
{
for (int i = 1; i <= 10; i++)
{
System.Threading.Thread.Sleep(500);
System.Console.WriteLine(i);
}
}
}
main入口:
WorkflowInvoker启动工作流,代码如下:
static void Main(string[] args)
{
//实例化工作流
Activity workflow1 = new Workflow1();
//使用WorkflowInvoker管理工作流
WorkflowInvoker.Invoke(workflow1);
WorkflowInvoker.Invoke(workflow1);
Console.ReadKey();
}
WorkflowApplication启动工作流,代码如下:
static void Main(string[] args)
{
//Activity workflow1 = new Workflow1();
//WorkflowInvoker.Invoke(workflow1);
WorkflowApplication instance1 = new WorkflowApplication(new Workflow1());
WorkflowApplication instance2 = new WorkflowApplication(new Workflow1());
instance1.Run();
instance2.Run();
Console.ReadKey();
}
总结
工作流就好像不是实际存在的东西,需要依靠宿主去启动,或者进行其他的活动。两种宿主各有千秋,如果简单的流程,使用WorkflowInvoker足够了。但是如果流程比较复杂,需要持久化入数据库,就得用WorkflowApplication。有这两种宿主对象,对工作流的管理就方便了很多。WorkflowServiceHost承载工作流服务的,了解还不是很深刻,如果有大牛了解,欢迎评论指导。