您的位置:首页 > 其它

《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);
}
}


 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐