宿主和工作流:通信的两个世界:第一部分






3.88/5 (7投票s)
第一部分:最简单的通信案例:通过参数从宿主 -> 工作流进行通信。
引言
工作流与宿主应用程序之间的相互通信并不是一件容易实现的事情,因为宿主和工作流运行在不同的线程中。微软开发了一种通信结构来简化这个问题。它创建了一种特殊的方法和类来处理通信。
在这一系列文章中,我将尝试展示实现通信的各种可能性,从最简单的案例到更复杂的案例。我并不打算详尽无遗,但我会努力给出一个全景式的概述,以便让你对这个主题有一个好的了解。
因为我不喜欢太长的文章,所以我把它分成了以下几个部分
- 第一部分:最简单的通信案例:通过参数从宿主到工作流进行通信。
- 第二部分:工作流 -> 宿主通过 CallExternalMethod 活动进行通信.
- 第三部分:宿主 -> 工作流通过 HandleExternalEvent 活动进行通信.
- 第四部分:通信类的组织:通信管理器,wca.exe 工具,以及 wca.exe 的 Wwca.exe Windows 前端.
- 第五部分:使用 Correlation 参数与工作流实例进行通信.
背景
在第一篇文章中,我将通过一个例子解释一种将信息从宿主传递到工作流的基本方法。这种将初始化参数传递给工作流的可能性在只需要在工作流启动时传递信息并且之后不再需要通信的情况下非常有用。
考虑一种情况,你想从计算机读取一个文件,并从中读取指定数量的字符。
我们可以传递两个参数(文件路径和要从文件中返回的字符数),工作流将在内部消息框中显示信息(参见图 1)。
你可以看到,线程之间的障碍在工作流调用时被跨越了,消息直接在工作流线程中显示。我们使用一个控制台应用程序和一个顺序工作流来解释在这种情况下如何进行。
Using the Code
在 Visual Studio 2008 中创建一个顺序控制台工作流项目。此操作将创建一个 *Program.cs* 控制台文件和 *Workflow1.cs* 文件。在遵循以下步骤之前,你应该在项目的“引用”中添加对 *System.Windows.Form* 的引用。
将参数传递给工作流的步骤相对简单。它们显示在这里
- 在 *Workflow1.cs*(代码)中创建两个属性来保存输入参数,如下面的代码段所示
- 创建一个
Dictionary
来保存工作流的输入参数。此操作发生在宿主应用程序中。我们必须创建一个具有以下结构的Dictionary
- 将创建的字典传递给工作流。
public sealed partial class Workflow1: SequentialWorkflowActivity
{
//Enter the variables that hold the parameters as properties
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; }
}
Dictionary<string, object>
字典中的每个对象必须具有与在工作流中第 1 点声明的属性相同的索引名称。在我们的例子中,属性是“FilePath
”和“Quantity
”。
在示例中,我们可以将这些参数作为行参数输入,但你可以从任何地方获取这些参数的值。在下面的代码中,你可以看到如何准备字典,以便从局部变量填充工作流属性
//Create a dictionary to pass parameter to workflow....
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);
当工作流在宿主应用程序中创建时,CreateWorkflow
函数有一个重载方法,它给了你机会用任意数量的参数来初始化工作流。你可以在以下代码段中看到该函数
WorkflowInstance instance =
workflowRuntime.CreateWorkflow( typeof(SimplestWFHostComm.Workflow1),
argumentDictionary );
instance.Start();
工作流运行时会实例化工作流,并自动尝试将字典中的值与工作流中声明的属性进行匹配。如果匹配,则会将值传输到属性。如果你传递了一个在字典中不存在与工作流中属性对应的名称,或者传递了一个类型错误的对象的,则会引发一个类型为 ArgumentException
的异常。
就这样!要完成项目,请参阅附件中的代码,并将程序逻辑集成到你的项目中,或者如果你愿意,可以运行附件中的代码。
我默认使用一个位于 *System32* 的文件,我认为所有 Windows 操作系统都有它。但也许你的系统里没有!随时修改此参数以使用你有的文件。仅将文本文件用作 FilePath
参数,如果你使用包含空格的文件或路径,则必须用引号将其括起来。
恢复
将初始化参数从宿主传递到工作流的三个基本步骤是
- 在工作流中创建必要的属性以接收参数。
- 在宿主应用程序中创建一个
Dictionary
实例来保存初始化参数。 - 将
Dictionary
作为参数传递给工作流运行时CreateWorkflow
方法。
如你所见,从宿主传递初始化参数到工作流并不复杂。这种相对简单的技术对于许多实际情况也非常有用,但并不充分。
在我们考虑的例子中,我们只需要将信息传递给工作流,但当工作流需要将信息传递给宿主应用程序时会怎么样?我们将在下一篇文章中讨论这个问题。