《Pro WF Windows Workflow in .NET 4》-- WhorkFlow hosting 之 参数的传递
2011-11-15 14:06
561 查看
WorkFlow程序需要有一个Host程序对其进行运行管理。这个Host可以是一个控制台程序,也可以是IIS ,wpf , winform , windows serverce等。在WrokFlow项目模板中也提供了一个叫Workflow Console Application的模板。使用它我们可以创建一个基于WF的控制程序,在本书中大部分程序都是使用它HOST的。
理解workflowinvoker 类
要对Workflow进行host就要了解一个类,workflowinvoker 类。
这个类提供了一种简单的方法去完成workflow 或者 activity 的执行。它允许你去执行一个activity在当前线程上,通过一个简单方法的调用。在host和workflow中将使用同一线程执行,也就是当前主线程。这也就消除了代码需要在当前线程和workflow线程中来回切换的问题。这也消除了workflowinvoker类需要提供一个广泛的状态通知及相关事件的问题。
虽然这个方法很简单,这个类还是提供了一些可选项为workfow或者 activity的执行。这些将在下面进行描述。
使用静态方法
使用WorkflowInvoker类的其中一个方法就是通过一个设置好的静态方法Invoke。使用一个Invoke方法,你能创建一个workflow实例,你甚至可以传递一些需要的参数为这个实例。如果workflow确实需要一些参数,你可以传递它们通过dictionary集合。invoke方法的返回值也是一个 dictionary的集合。这个方法还有其它一些重载,允许你传入超时限制或者输入参数。下面让我们来看一下这些方法的重载。
public static
IDictionary<string ,object> Invoke(Activity
workflow);
public static
IDictionary<string ,object> Invoke(Activity
workflow, IDictionary<string, object> inputs);
public static
IDictionary<string ,object> Invoke(Activity
workflow, TimeSpan timeout);
public static
IDictionary<string ,object> Invoke(Activity
workflow, IDictionary<string, object> inputs,
TimeSpan timeout);
超时值是指允许workflow执行的最大时间限制,当超过这个时间后,程序就会引发system.TimeoutException异常。
这个类也包括了一些执行单个activity的静态类。这个activity必须继承于一个activity基类(Activity<TResult>, CodeActivity<TResult>, AsyncCodeActivity<TResult> , NativeActivity<TResult>)。它返回一个输出参数名叫Result。这些Invoke方法接受一个泛型值为TResult的activity.下面是这些方法的重载。
public static TResult Invoke<TResult>(Activity<TResult> workflow);
public static TResult Invoke<TResult>(Activity<TResult> workflow,
IDictionary<string, object> inputs);
public static TResult Invoke<TResult>(Activity<TResult> workflow,
IDictionary<string, object> inputs,
TimeSpan timeout);
public static TResult Invoke<TResult>(Activity<TResult> workflow,
IDictionary<string, object> inputs,
out IDictionary<string,object> additionlOutputs,TimeSpan
timeout);
使用实例化方法
除了使用静态方法外,你还可以创建一个WrokflowInvoker类的实例并执行工作流,使用实例方法。使用实例方法给你提供了一些额外的选项。如增加workflow扩展的能力(在执行前为其赋值)。当创建好一个workflowInvoker实例后,你可以调用一个或者多个Invoke方法来执行工作流。
public IDictionary<string, object> Invoke();
public IDictionary<string, object> Invoke(IDictionary<string,object> inputs);
public IDictionary<string, object> Invoke(TimeSpan
timeout);
public IDictionary<string, object> Invoke(IDictionary<string,object> inputs,
TimeSpan timeout);
workflowInvoker类被设计来执行一个workflow或者activity在当前的线程当中,然而,它也支持通过异步的方式调用。方法如下:
public void InvokeAsync();
public void InvokeAsync(IDictionary<string,object> inputs);
public void InvokeAsync(object
userState);
public void InvokeAsync(TimeSpan
timeout);
public void InvokeAsync(IDictionary<string,object> inputs,
object userState);
public void InvokeAsync(IDictionary<string,object> inputs,
TimeSpan timeout);
public void InvokeAsync(TimeSpan
timeout, object userState);
public void InvokeAsync(IDictionary<string,object> inputs,
TimeSpan timeout,object
userState);
当你使用一个或者多个InvokeAsync方法的时候,你必须增加一个handler到InvokeCompleted事件中,目的是接收任何返回的输出参数并对其进行处理。
与它们的名字相反,这些方法并不执行workflow或者activity在同一个线程中。 InvokeAsync方法与Invoke方法的不同仅仅在于当它变为空闲状态时,如何进行恢复(这句话不太明白是什么意思)。
下面阐述下这之间的区别。想象有一个workflow它有一些内部的处理过程,也包含了一个delay activity。当这个workflow以Invoke方法执行时,这个工作流执行完delay后将重新回到host主线程中继续执行。如果使用的是invokeasync方法执行,则它会返回到线程中的一个后台线程执行。
workflowINvoker类提供了一个BegionInvoke和EndInvoke方法,这些方法与操作InvokeAsync方法相似,但是它们只支持.net异步构架。
从表面上看InvokeAsync与BeginInvoke之间的差别是很微小的。然后在后台,他们的操作实际上是不一样的。InvokeAsync使用的是当前异步上下文。然而BegionInvoke却不是的。这意味着你可以手动设置SynchronizationContext类的Current属性为不同的synchronization上下文对象。这将改变InvokeAsync的行为。比如:你可能希望去使用synchroniozation context在WPF, WIN FORM 或者 asp.net应用程序中,如果你执行的workflow需要相互影响在这些架构中。
使用workflowinvoker 静态方法
不多解释,直接上代码首先展示一个简单的宿主workflow的方法,通过参数进行传递数据。代码如下
class Program { static void Main(string[] args) {Console.WriteLine("Host: about to run workflow - thread:{0}", Thread.CurrentThread.ManagedThreadId);
try
{
//调用invoke方法并返回IDictionary.传入一个参数ArgNumberToEcho
//HostingDemoWorkflow是一个WF的类
IDictionary<string, object> output = WorkflowInvoker.Invoke(new HostingDemoWorkflow(), new Dictionary<string, object> { {"ArgNumberToEcho",1001}});
Console.WriteLine("Host: workflow completed - thread:{0}-{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, output["Result"]);
}
catch (Exception ex)
{
Console.WriteLine("Host: workflow exception :{0}:{1}", ex.GetType(), ex.Message);
}
}
}
第二种,通过属性传递参数
class Program {static void Main(string[] args) {Console.WriteLine("Host: about to run workflow - thread:{0}", Thread.CurrentThread.ManagedThreadId);
try
{
//调用invoke方法并返回IDictionary.传入一个参数ArgNumberToEcho
//HostingDemoWorkflow是一个WF的类
HostingDemoWorkflow wf = new HostingDemoWorkflow();
wf.ArgNumberToEcho = 1002;//通过属性传值
IDictionary<string, object> output = WorkflowInvoker.Invoke(wf));
Console.WriteLine("Host: workflow completed - thread:{0}-{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, output["Result"]);
}
catch (Exception ex)
{
Console.WriteLine("Host: workflow exception :{0}:{1}", ex.GetType(), ex.Message);
}
} }
如果你需要使用超时参数,代码可以像这样写
HostingDemoWorkflow wf = new HostingDemoWorkflow(); wf.ArgNumberToEcho = 1002;//通过属性传值 IDictionary<string, object> output = WorkflowInvoker.Invoke(wf, TimeSpan.FromSecondes(1));
除了上面host一个workflow外,还可以host一个activity.首先定义一个codeActivity;
namespace ActivityLibrary { //CodeActivity<String>说明此activity有一个类型为string的返回值 public sealed class HostingDemoActivity : CodeActivity<String> { // 定义了一个int32的输入参数。 public InArgument<Int32> NumberToEcho { get; set; } // If your activity returns a value, derive from CodeActivity<TResult> // and return the value from the Execute method. protected override String Execute(CodeActivityContext context) { // 通过context.GetValue(字段)的方式获取传入的参数内容。 return String.Format("Result is {0}- thread:{1}", context.GetValue(this.NumberToEcho),System.Threading.Thread.CurrentThread.ManagedThreadId); } } }
然后执行这个acitivity。
static void Main(string[] args)
{ Console.WriteLine("Host: about to run workflow - thread:{0}", Thread.CurrentThread.ManagedThreadId); try { HostingDemoActivity wf = new HostingDemoActivity();//我们定义的activity实例 wf.NumberToEcho = 1003;//定义的输入属性 string output = WorkflowInvoker.Invoke<string>(wf);//用invoke泛型方法调用 Console.WriteLine("Host: workflow completed - thread:{0}-{1}", System.Threading.Thread.CurrentThread.ManagedThreadId, output); } catch (Exception ex) { Console.WriteLine("Host: workflow exception :{0}:{1}", ex.GetType(), ex.Message); } }
相关文章推荐
- Pro WF: Windows Workflow in .NET 3.0
- Pro WF: Windows Workflow in .NET 3.5
- Foundations of WF: an Introduction to Windows Workflow Foundation (Expert's Voice in .Net)
- Brian Myers, «Foundations of WF: an Introduction to Windows Workflow Foundation (Expert's Voice in .Net)
- Beginning WF Windows Workflow in .NET 4.0
- WF (Windows Workflow Foundation) 工作流学习(二)一个Asp.Net 与 顺序工作流 结合的例子
- 《WF高级程序设计》(《Pro WF:Windows Workflow in .NET 3.5》中文版)上市
- Pro WPF in C# 2008 Windows Presentation Foundation with .NET 3.5(第二版)概览
- WF (Windows Workflow Foundation) 工作流学习(一)一个Asp.Net 状态机验证程序
- 和我一起学Windows Workflow Foundation(2)-----让WF通过参数接收数据
- WF (Windows Workflow Foundation) 工作流学习(一)一个Asp.Net 状态机验证程序
- Pro WPF in C# 2008: Windows Presentation Foundation with .NET 3.5, Second Edition
- WF (Windows Workflow Foundation) 工作流学习(一)一个Asp.Net 状态机验证程序
- Pro .NET 2.0 Windows Forms and Custom Controls in C#
- Hands-on Labs for Windows® Workflow Foundation in C# and VB.NET
- 和我一起学Windows Workflow Foundation(2)-----让WF通过参数接收数据 [转]
- ado.net 参数传递之 in
- WF (Windows Workflow Foundation) 工作流学习(二)一个Asp.Net 与 顺序工作流 结合的例子
- 和我一起学Windows Workflow Foundation(2)-----让WF通过参数接收数据
- WF (Windows Workflow Foundation) 工作流学习(二)一个Asp.Net 与 顺序工作流 结合的例子