代码改变世界

《WF编程》系列之9 - 编译工作流:使用WFC.EXE

2007-04-09 10:42  Windie Chai  阅读(...)  评论(...编辑  收藏

2.3.2 编译工作流

Windows Worfklow提供两种工作流编译方式,通过WorkflowCompiler类(位于System.Workflow.ComponentModel.Compiler名称空间)来编译,或者使用一个命令行编译工具(其实还是通过WorkflowCompiler类实现编译的).

工作流编译器在将工作流定义转换为类型时要遵循一定的步骤.首先是验证工作流定义中的每个活动.我们知道,活动可以定义自己的验证逻辑,举例来说,如果CodeActivity的ExecuteCode事件没有指定的话,它将抛出一个验证失败的错误.验证通过之后.编译器会在一个临时目录中生成源代码(默认语言是C#).最后将生成的源代码编译为一个程序集(就像普通的C#或Visual Basic.NET代码被编译一样).

2.3.2.1 用Wfc.exe编译

WF的命令行编译器叫做wfc.exe.用它来编译工作流,我们需要传递一些参数给它.第一个参数是XOML文件的名称,假设我们的XAML叫做pureXAML.xoml.然后使用-out指令来传递编译后程序集的名称.如果有一些自定义活动是在另外的程序集中定义的,我们需要使用-r指令来引用这些程序集.例如引用一个叫做chapter2_Host.exe的可执行程序集来编译工作流:

wfc.exe purexaml.xoml –r:chapter2_host.exe –out:purexaml.dll

WOW!(不是Vista的广告,也不是某图形处理软件书系的书名,更加不是某网游,仅表示欢呼^O^)

现在我们得到了一个可以在宿主应用程序中使用的程序集.我们可以在宿主应用程序中通过调用Type.GetType并传递assembly-qualified类型名称来动态的加载这个程序集.assembly-qualiied类型名称中包含类型的名称和类型所在的程序集的名称.我们通过x:Class特性指定工作流类型的名称MyWorkflow,在编译的时候又指定了程序集的名称purexaml,所以assembly‑qualiied名称是MyWorkflow,purexaml.下面的代码示范加载程序集并执行工作流:

 

using (WorkflowRuntime runtime = new WorkflowRuntime())

using (AutoResetEvent waitHandle = new AutoResetEvent(false))

{

    runtime.WorkflowCompleted 
+= delegate { waitHandle.Set(); };

    runtime.WorkflowTerminated 
+= delegate { waitHandle.Set(); };

    Type workflowType 
= Type.GetType("MyWorkflow, purexaml");

    WorkflowInstance instance 
= runtime.CreateWorkflow(workflowType);

    instance.Start();

    waitHandle.WaitOne();

}

前边提到过,工作流是在CLR线程池中的一个线程上异步执行的,所以我们需要等待AutoResetEvent事件的信号来工完成作流. 

线程池为异步操作管理后台线程.创建线程是相当”昂贵”的操作,但是通过重复使用线程的方法,线程池可以在应用程序的生命周期内为这笔开销”分期付款”.当一个操作想要在后台线程上工作时,Runtime从池中分配一个线程给它;当操作完成后,Runtime又将线程还给线程池等待再次分配.