WF兼有很多角色,如編程模型、運行時引擎以及工具集等,它使我們很容易創建基于工作流的應用。這里主要分析一下VS2008下順序工作流控制臺應用程序的模板,并了解幾個常見的活動。
順序工作流控制臺應用程序模板
WF提供兩種類型的工作流:順序工作流、狀態機工作流。這兩個工作流分別從SequentialWorkflowActivity, StateMachineWorkflowActivity派生而來。VS2008提供了順序工作流控制臺應用程序和類庫兩種模板,本文主要介紹順序工作流控制臺應用程序模板。
創建工作流項目
具體步驟省略,詳細請參見參考文獻所示。查看生成的工作流代碼如下:

Code
public sealed partial class Workflow1: SequentialWorkflowActivity
{
public Workflow1()
{
InitializeComponent();
}
}
很容易看出,新建的工作流Workflow1是從SequentialWorkflowActivity派生。
新建的工作流只有起始點,沒有任何活動。這里我們添加一個Code activity。添加了這個活動后,我們發現,這個活動出現了錯誤,是因為ExecuteCode沒有設定,這里只需雙擊Code activity即可,并在代碼文件中添加Console.WriteLine("Hello, World!");。一個Hello, World!工作流就這樣完成了。
解析工作流調用代碼(宿主程序代碼)

Code
static void Main(string[] args)
{
// 創建工作流運行時引擎,為工作流初始化提供可配置的運行環境
using(WorkflowRuntime workflowRuntime = new WorkflowRuntime())
{
// 防止工作流線程沒有執行完成,主線程就退出。
// 工作流線程完成后,通過Set方法通知主線程,工作流線程已經完成。
AutoResetEvent waitHandle = new AutoResetEvent(false); // 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(); // 通知主線程,工作流執行完畢
};
WorkflowInstance instance = workflowRuntime.CreateWorkflow(typeof(WorkflowDemo1.Workflow1));
instance.Start();
// 主線程在此阻塞,直到工作流線程發出通知(waitHandle.Set())
waitHandle.WaitOne();
}
}
注意:
1. 通過WorkflowRuntime類為工作流初始化提供可配置的運行環境
2. 通過AutoResetEvent類,協調主線程和工作流線程。
3. 通過WorkflowInstance類創建工作流實例。
創建一個比Hello, World更高級的工作流
作業:創建一個工作流,使之支持一個文件加中的所有文件拷貝到另外一個文件夾。
思路:
1.創建一個代碼活動,解析從宿主程序傳來的源文件夾和目的文件夾;
2.創建一個循環活動(一個個拷貝,直到所有文件拷貝完畢)
在循環活動中嵌入代碼活動,完成單個文件的拷貝
這里需要解釋幾個問題:
循環活動條件設置
在while activity活動中,規則采用聲明性規則條件,當前是第幾個文件 < 總共幾個文件。在后臺生成如下文件workflow.rules:

Code
<RuleDefinitions xmlns="http://schemas.microsoft.com/winfx/2006/xaml/workflow">
<RuleDefinitions.Conditions>
<RuleExpressionCondition Name="條件1">
<RuleExpressionCondition.Expression>
<!--操作符定義為小于號-->
<ns0:CodeBinaryOperatorExpression Operator="LessThan" xmlns:ns0="clr-namespace:System.CodeDom;Assembly=System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<!--左邊的值-->
<ns0:CodeBinaryOperatorExpression.Left>
<ns0:CodeFieldReferenceExpression FieldName="currentFile">
<ns0:CodeFieldReferenceExpression.TargetObject>
<ns0:CodeThisReferenceExpression />
</ns0:CodeFieldReferenceExpression.TargetObject>
</ns0:CodeFieldReferenceExpression>
</ns0:CodeBinaryOperatorExpression.Left>
<!--右邊的值-->
<ns0:CodeBinaryOperatorExpression.Right>
<ns0:CodePropertyReferenceExpression PropertyName="totalFiles">
<ns0:CodePropertyReferenceExpression.TargetObject>
<ns0:CodeThisReferenceExpression />
</ns0:CodePropertyReferenceExpression.TargetObject>
</ns0:CodePropertyReferenceExpression>
</ns0:CodeBinaryOperatorExpression.Right>
</ns0:CodeBinaryOperatorExpression>
</RuleExpressionCondition.Expression>
</RuleExpressionCondition>
</RuleDefinitions.Conditions>
</RuleDefinitions>
在后臺,通過
System.Workflow.Activities.Rules.RuleConditionReference ruleconditionreference1 = new System.Workflow.Activities.Rules.RuleConditionReference();
ruleconditionreference1.ConditionName = "條件1";
this.whileActivity1.Condition = ruleconditionreference1;
進行加載到循環活動中。
宿主程序和工作流的通訊
如何向工作流中傳遞參數:
在工作流中定義成員變量:
public string toFolder { get; set; }
public string fromFolder { get; set; }
public int totalFiles { get; set; }
在宿主程序初始化工作流實例的時候,將參數傳入
var parameters = new Dictionary<string, object>();
parameters.Add("fromFolder", @"K:"test");
parameters.Add("toFolder", @"K:"backup");
WorkflowInstance instance =
workflowRuntime.CreateWorkflow(
typeof(WorkflowDemo1.Workflow1), parameters);
如何從工作流中獲取參數:
從WorkflowCompletedEventArgs e 中,即可獲取工作流中的相關信息,如:e.OutputParameters["totalFiles"]。
參考文獻
本翻譯沒有按照原文,詳細請查閱
http://social.msdn.microsoft.com/content/en-us/msft/netframework/wf/learn/Intro-SequentialWorkflows