本文内容来自Microsoft Hands-on Labs for Windows Workflow Foundation中的HOL03中的第一个练习,其中包括三个任务:
添加一个验证来检查Email参数。
Ø 创建一个新的Console Application Project
Ø 监听Runtime Events
Ø 配置Runtime Services
在这个练习前,需要作一些准备工作。
在c:\Windows Workflow Foundation\Labs\Lab03\Resources\路径下找到一个批处理文件CreateDatabaseObjects.cmd,和它一起的还有一个SQL脚本文件Create_TrackingStore.sql。
在执行这个批处理文件之前需要确认已经安装好SQL Server 2005或者它的Express版本并正常运行,然后运行这个批处理文件,它会建立好相应的数据库部分的内容。
这个练习会创建一个简单的控制台应用程序Console Application,instantiate the workflow runtime这个不会翻译,初始化一个工作流运行时,然后启动一个工作流。
1.重新创建一个Sequential Workflow Console Application项目。
Name:HostingWorkflowRuntime
Location:c:\Windows Workflow Foundation\Labs\Lab03\
2.将Workflow1.cs文件重命名为SimpleWorkflow.cs。
3.在SimpleWorkflow.cs设计视图上拖放一个Code activity。设置Name属性为working。
4.双击这个working Code activity,会生成一个处理程序中ExecuteCode对应的方法。在方法中输入如下代码:
Console.WriteLine("Here in working_ExecuteCode.");
5.在解决方案资源管理器中找到Program.cs文件,查看它的代码。代码中已经自动生成了Main函数,并且在其中进行了工作流实例的创建和运行。尽管如此,在你看到运行结果显示之前他就完成并退出了。因此,在代码的后面,即启动工作流实例和等待的后面,加入如下代码。
Console.WriteLine("Workflow Completed - press ENTER to continue");
Console.Read();
6.现在按F5编译生成整个解决方案并运行。就会看到如下效果:
7.这样就可以看到执行结果了,按下回车键才会退出显示。
任务一完成。
8.在这个Host中,可以做很多事情,控制工作流运行时或者查看发生了什么。在这个任务中将订阅一些运行时事件。让我们开始,订阅Started和Stopped事件。在Main方法中现有的代理部分的代码下增加如下代码:
workflowRuntime.Started += new EventHandler<WorkflowRuntimeEventArgs>(workflowRuntime_Started);
workflowRuntime.Stopped += new EventHandler<WorkflowRuntimeEventArgs>(workflowRuntime_Stopped);
9.然后为这两个代理添加对应的方法。在workflowRuntime_Started方法中,参数sender是WorkflowRuntime类型的变量,可以从中得到工作流运行时加载时的所有服务的集合。可以使用foreach在控制台中显示出这些服务。
static void workflowRuntime_Started(object sender, WorkflowRuntimeEventArgs e)
{
WorkflowRuntime w = (WorkflowRuntime)sender;
ICollection<object> services = w.GetAllServices(typeof(object));
foreach (object o in services)
{
Console.WriteLine("Service of type " + o.ToString() + " started.");
}
}
10.在workflowRuntime_Stopped方法中添加了Console.WriteLine语句,用来标识执行到了这里。
static void workflowRuntime_Stopped(object sender, WorkflowRuntimeEventArgs e)
{
Console.WriteLine("Runtime stopped event.");
}
11.按F5执行结果如下:
12.下面添加一些想要知道的事件。订阅WorkflowResumed和WorkflowSuspended事件。在Main方法中加入以下代码:
workflowRuntime.WorkflowResumed += new EventHandler<WorkflowEventArgs>(workflowRuntime_WorkflowResumed);
workflowRuntime.WorkflowSuspended += new EventHandler<WorkflowSuspendedEventArgs>(workflowRuntime_WorkflowSuspended);
13.对这个两个代理指向的方法中添加如下代码:
static void workflowRuntime_WorkflowSuspended(object sender, WorkflowSuspendedEventArgs e)
{
Console.WriteLine("In WorkflowSuspended, reason: " + e.Reason);
}
static void workflowRuntime_WorkflowResumed(object sender, WorkflowEventArgs e)
{
Console.WriteLine("In WorkflowResumed");
}
14.在Main方法中需要作一下修改,传递一个string类型的参数来调用Suspend方法。这个string类型的参数将作为WorkflowSuspended方法中的WorkflowSuspendedEventArgs参数。添加如下代码:
在instance.Start();之后添加
instance.Suspend("Reason we are suspending the workflow.");
instance.Resume();
15.按F5编译运行,结果如下:
这里碰到了一个错误,没有调试成功。在Suspended方法中WorkflowSuspendedEventArgs参数在编程对象模型中只提供了Reason属性,但是在事件中如果引用这个对象模型的属性则会出现错误。找不到方法:“System.String System.Workflow.Runtime.WorkflowSuspendedEventArgs.get_Reason()。我在调试的时候快速监视这个参数,发现了如下的情况
如图,只看到了提供了Error属性,但是从对象模型却只能放问到Reason属性
下面给大家展示更奇怪的现象,在即时窗口中出现了如下的结果
16.还有其他的方法可以在host上set up the runtime environment。可以使用App.Config文件来对runtime进行设置并使用。也可以使用WorkflowRuntime.AddService和WorkflowRuntime.RemoveService其中之一。
任务二完成。
17.可以通过添加一个配置文件来改变运行时的行为。
18.添加一个“应用程序配置文件”文件名为App.config。在如下目录中找到相应的文本文件用其中的内容覆盖配置文件中的内容:
C:\Windows Workflow Foundation\Labs\Lab03\Resources\application configuration file.txt
19.为了使用这个配置文件,需要引入命名空间System.Configuration。
20.配置文件中<listeners>标签,指定了一个要记录日志的文件。例如,下面内容会将执行时的跟踪信息将记录到同一目录下的WFHOLTrace.log文件中。在应用程序每次运行并没有被删除,所以文件的大小会随之增长。
<listeners>
<add name="myListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="WFHOLTrace.log" />
</listeners>
21.如果需要对记录入跟踪日志文件的信息类型进行选择,可以有5中类型可供选择,打开或关闭跟踪。WorkflowRuntime记录了以下类型的信息:Runtime、Tracking、Host、Activity、LogTraces。跟踪默认是关闭的,如果需要打开则要在配置文件中加入<switches>标签进行说明。
<system.diagnostics>
<switches>
<add name="WorkflowTraceToDefault" value="1" />
<add name="Host" value="All" />
<add name="Runtime" value="All" />
<add name="Tracking" value="All" />
<add name="Activity" value="All" />
</switches>
<trace autoflush="true" indentsize="4">
<listeners>
<add name="myListener"
type="System.Diagnostics.TextWriterTraceListener"
initializeData="WFHOLTrace.log" />
</listeners>
</trace>
</system.diagnostics>
22.为了使用配置文件需要告诉运行时在哪查看。这样就需要在声明或初始化WorkflowRuntime变量作一些小的改动。将Program.cs文件中的Main方法中修改如下:
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
修改为
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime("ConsoleApplication"))
23.这样会告诉运行时去配置文件中查找名字为"ConsoleApplication"的<section>标签。用<Services>标签可以为同上个标签一起的配置信息添加其它的服务,例如Microsoft SQL Server连接字符串。
<configSections>
<section name="ConsoleApplication"
type="System.Workflow.Runtime.Configuration.WorkflowRuntimeSection,
System.Workflow.Runtime, Version=3.0.00000.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35" />
</configSections>
24.按F5运行应用程序。当应用程序使用配置文件运行时,会打印出加载的服务如下:
图中可以看出,加载时根据配置文件加载了两个SQL服务。
25.在代码中建立SqlTrackingService实例,首先删除配置文件并修改Main方法中的如下代码:
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime("ConsoleApplication"))
将"ConsoleApplication"从WorkflowRuntime实例中删除掉。如下:
using (WorkflowRuntime workflowRuntime = new WorkflowRuntime())
26.在using语句中加入如下代码
string connectionString = "Initial Catalog=TrackingStore; " + "Data Source=localhost\\SQLEXPRESS; " + "Integrated Security=SSPI;";
workflowRuntime.AddService(new System.Workflow.Runtime.Tracking.SqlTrackingService(connectionString));
27.按F5运行结果如下:
图中加载出了SqlTrackingService服务实例。
任务三完成。
参考资料: