在CodeProject中有一篇介绍宿主程序如何和工作流进行交互,使用wf提供的两个活动就可以实现,分别是callExternalMethodActivity1和handleExternalEventActivity1活动,在后面会详细介绍。
宿主和工作流的交互是非常常用的,因为他们是运行在不同的线程中的。
首先介绍如何从宿主传递数据给工作流,一般都是初始化的数据,例如,工作流什么时候启动等,除了这些我们就不需要其他的交互了。
可以想象一种情况,我们想要从计算机读取一个文件,读取一定数量的字符。
我们可以想象一个这样的程序,你能传递两个参数(文件的路径和字符的数量),在工作流的内部使用MessageBox显示文件的信息。请看下图
User输入参数,运行控制台程序,控制台程序运行在一个线程中,相当于前面提到的Host,工作流运行在另外一个线程中,在Host要初始化工作流并且传递刚才输入的参数,在工作流中根据参数打开文件,读取一定数量的字符内容,用弹出窗体来显示内容,User看到内容。
在以往的学习中我们已经知道,给工作流传递参数,我们要使用Dictionary<string, object> ,
工作流类的完整代码如下
using System;
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace com.kimbanx.sharepoint.wf
{
public partial class Workflow1 : SequentialWorkflowActivity
{
string _filepath = string.Empty;
int _quantity = 0;
//Variable to hold the result
string _result = string.Empty;
/// <summary>
/// The Property name must be the same as the object in the
/// input parameter dictionary
/// </summary>
public int Quantity
{
get { return _quantity; }
set { _quantity = value; }
}
/// <summary>
/// The Property name must be the same as the object in the
/// input parameter dictionary
/// </summary>
public string FilePath
{
get { return _filepath; }
set { _filepath = value; }
}
}
}
using System.ComponentModel;
using System.ComponentModel.Design;
using System.Collections;
using System.Drawing;
using System.Linq;
using System.Workflow.ComponentModel.Compiler;
using System.Workflow.ComponentModel.Serialization;
using System.Workflow.ComponentModel;
using System.Workflow.ComponentModel.Design;
using System.Workflow.Runtime;
using System.Workflow.Activities;
using System.Workflow.Activities.Rules;
namespace com.kimbanx.sharepoint.wf
{
public partial class Workflow1 : SequentialWorkflowActivity
{
string _filepath = string.Empty;
int _quantity = 0;
//Variable to hold the result
string _result = string.Empty;
/// <summary>
/// The Property name must be the same as the object in the
/// input parameter dictionary
/// </summary>
public int Quantity
{
get { return _quantity; }
set { _quantity = value; }
}
/// <summary>
/// The Property name must be the same as the object in the
/// input parameter dictionary
/// </summary>
public string FilePath
{
get { return _filepath; }
set { _filepath = value; }
}
}
}
Host(就是我们这里的控制台程序)的代码如下
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
namespace CallExternalMethodDemo
{
class Program
{
static void Main(string[] args)
{
using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {waitHandle.Set();};
workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
};
Dictionary<string, object> argumentDictionary = new Dictionary<string, object>();
//Pass the first parameter: the file path. You must use the same name that was defined as variable in the workflow.
argumentDictionary.Add("FilePath", _filepath);
argumentDictionary.Add("Quantity", _readQuantity);
WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(CallExternalMethodDemo.Workflow1),argumentDictionary);
instance.Start();
waitHandle.WaitOne();
}
}
}
}
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Workflow.Runtime;
using System.Workflow.Runtime.Hosting;
namespace CallExternalMethodDemo
{
class Program
{
static void Main(string[] args)
{
using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
AutoResetEvent waitHandle = new AutoResetEvent(false);
workflowRuntime.WorkflowCompleted += delegate(object sender, WorkflowCompletedEventArgs e) {waitHandle.Set();};
workflowRuntime.WorkflowTerminated += delegate(object sender, WorkflowTerminatedEventArgs e)
{
Console.WriteLine(e.Exception.Message);
waitHandle.Set();
};
Dictionary<string, object> argumentDictionary = new Dictionary<string, object>();
//Pass the first parameter: the file path. You must use the same name that was defined as variable in the workflow.
argumentDictionary.Add("FilePath", _filepath);
argumentDictionary.Add("Quantity", _readQuantity);
WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(CallExternalMethodDemo.Workflow1),argumentDictionary);
instance.Start();
waitHandle.WaitOne();
}
}
}
}
从Host给工作流传递数据的三个基本步骤是:
1、在工作流中创建必要属性,用来接收传递过来的数据
2、在Host程序中创建 Dictionary<string, object>的实例,用来存储初始化参数数据
3、使用CreateWorkflow的重载方法,将 Dictionary<string, object>的实例作为参数传递给工作流
上面的例子中我们只需要给工作流传递数据,但是什么时候工作流需要传递数据给我们的Host呢?在接下来的文章中我们将会讲到。
谢谢!