WF4.0 活动详解<第一篇>:基础活动与核心概念
Windows Workflow Foundation (WF) 4.0 是微软推出的革命性工作流引擎,采用了全新的"活动为基础"的编程模型。与之前的 WF 3.5 不同,WF4.0 将工作流定义为活动的组合,每个活动都是一个可执行的代码单元,包含特定的业务逻辑或控制流功能。理解活动是掌握 WF4.0 的关键,本文将系统介绍 WF4.0 中的核心活动及其应用模式。
深入解析 Windows Workflow Foundation 4.0 的核心构件单元——活动(Activities),揭开工作流编程的神秘面纱
目录#
一、WF4.0活动模型概述#
在WF4.0中,活动是工作流的基本执行单元,所有工作流都是由活动组合而成。关键特性包括:
- 活动树结构:工作流本质上是树状结构的活动组合
- 复合活动:可包含子活动的容器(如Sequence、Flowchart)
- 执行上下文:每个活动运行在特定上下文中,共享变量和参数
- 书签机制:支持暂停和恢复执行的能力
- 异步支持:原生支持异步操作执行
graph TD
A[Workflow] --> B[Sequence]
B --> C[WriteLine]
B --> D[Assign]
B --> E[If]
E --> F[WriteLine 条件成立]
E --> G[WriteLine 条件不成立]
B --> H[Parallel]二、控制流活动详解#
1. Sequence#
最常用的复合活动,其子活动按顺序执行
new Sequence
{
Activities =
{
new WriteLine { Text = "步骤1" },
new WriteLine { Text = "步骤2" },
new WriteLine { Text = "步骤3" }
}
}最佳实践:避免在Sequence中放入长时间运行的操作,可能阻塞整个序列
2. Flowchart#
流程图样式的工作流,支持非线性执行路径
var flowchart = new Flowchart();
var step1 = new WriteLine { Text = "开始" };
var step2 = new WriteLine { Text = "处理业务" };
var step3 = new WriteLine { Text = "结束" };
flowchart.StartNode = step1;
flowchart.Nodes.Add(step1);
flowchart.Nodes.Add(step2);
flowchart.Nodes.Add(step3);
// 建立连接
flowchart.Connections.Add(new FlowStep
{
From = step1,
To = step2,
Condition = ExpressionServices.Convert<bool>(ctx => true)
});3. Parallel#
并行执行多个分支,适合独立任务并行处理
new Parallel
{
Branches =
{
new Sequence { Activities = { new WriteLine("分支1任务1"), Delay(2) } },
new Sequence { Activities = { new WriteLine("分支2任务1"), Delay(3) } }
}
}重要提示:Parallel不是真正的线程并行,而是基于协作式调度
4. If#
条件分支控制,根据布尔表达式选择执行路径
new If
{
Condition = new InArgument<bool>(ctx => orderAmount > 1000),
Then = new WriteLine { Text = "执行VIP流程" },
Else = new WriteLine { Text = "执行普通流程" }
}5. While/DoWhile#
循环控制结构,区别在于条件检查位置
int count = 0;
new While
{
Condition = new InArgument<bool>(ctx => count < 5),
Body = new Sequence
{
Activities =
{
new Assign<int>
{
To = new OutArgument<int>(ctx => count),
Value = new InArgument<int>(ctx => count + 1)
},
new WriteLine { Text = new InArgument<string>(ctx => $"当前计数: {count}") }
}
}
}6. Pick#
基于事件触发的分支选择,用于异步场景
new Pick
{
Branches =
{
new PickBranch // 电子邮件响应分支
{
Trigger = new Receive { ... },
Action = new WriteLine("收到邮件回复")
},
new PickBranch // 超时分支
{
Trigger = new Delay { Duration = TimeSpan.FromHours(1) },
Action = new WriteLine("超时未收到回复")
}
}
}适用场景:需要等待多种可能事件的处理流程(如审批流程)
三、基本操作活动#
1. Assign#
赋值操作,修改变量值
new Assign<string>
{
To = new OutArgument<string>(varCustomerName),
Value = new InArgument<string>("John Smith")
}2. WriteLine#
调试输出活动,开发时用于跟踪执行状态
new WriteLine
{
Text = new InArgument<string>(ctx => $"当前时间: {DateTime.Now}")
}3. Delay#
工作流暂停执行指定时间
new Delay
{
Duration = TimeSpan.FromMinutes(30) // 暂停30分钟
}重要:Delay使用工作流调度器的计时机制,非线程阻塞
4. InvokeMethod#
调用.NET类中的方法
new InvokeMethod
{
TargetObject = new InArgument<OrderService>(ctx => orderService),
MethodName = "ProcessOrder",
Parameters =
{
new InArgument<Order>(ctx => currentOrder)
}
}最佳实践:
- 避免调用长时间阻塞的方法
- 推荐使用异步方法版本InvokeMethodAsync
四、错误处理活动#
1. TryCatch#
结构化错误处理,类似C#的try-catch
new TryCatch
{
Try = new Sequence
{
Activities =
{
new InvokeMethod { ... } // 可能抛出异常的操作
}
},
Catches =
{
new Catch<ArgumentException>
{
Action = new ActivityAction<ArgumentException>
{
Handler = new WriteLine
{
Text = "参数错误!"
}
}
}
}
}2. Throw#
主动抛出异常
new Throw
{
Exception = new InArgument<Exception>(
ctx => new InvalidOperationException("状态异常"))
}五、变量与参数管理#
变量作用域规则:
- 变量在活动作用域内定义
- 子活动可访问父活动定义的变量
- 使用
Variable<T>声明工作流变量
var orderAmount = new Variable<decimal> { Name = "OrderAmount" };
new Sequence
{
Variables = { orderAmount },
Activities =
{
new Assign<decimal>
{
To = orderAmount,
Value = 199.99m
},
new WriteLine
{
Text = new InArgument<string>(ctx => $"订单金额: {orderAmount.Get(ctx)}")
}
}
}工作流参数:
- 使用
InArgument/OutArgument/InOutArgument声明 - 在工作流启动时传入初始值
- 在工作流完成后获取输出值
六、最佳实践与常见模式#
最佳实践#
- 单一职责原则:每个活动应有明确单一的功能
- 避免巨型Sequence:拆分为更小的可重用活动
- 异步操作模式:
new Sequence { Activities = { new InvokeMethodAsync { ... }, // 启动异步操作 new Delay { Duration = TimeSpan.FromSeconds(5) }, new WriteLine { Text = "后台处理中..." } } } - 超时处理模式:
new Parallel { CompletionCondition = true, // 任意分支完成则终止 Branches = { new Sequence { ... }, // 主任务 new Sequence { Activities = { new Delay(TimeSpan.FromMinutes(30)), new Throw(new TimeoutException()) } } } }
常见反模式#
- 阻塞线程的活动:调用Thread.Sleep()等阻塞方法
- 过度复杂的单一活动:包含过多业务逻辑
- 忽略取消处理:未实现CancellationScope
七、示例:订单处理工作流#
// 定义工作流变量
var order = new Variable<Order>("Order");
var isApproved = new Variable<bool>("IsApproved", false);
// 创建工作流
var workflow = new Sequence
{
Variables = { order, isApproved },
Activities =
{
// 接收订单
new Receive { ... },
// 验证订单
new If
{
Condition = new InArgument<bool>(ctx => order.Get(ctx).IsValid),
Then = new Sequence
{
Activities =
{
// 并行处理库存检查与信用检查
new Parallel
{
CompletionCondition = false, // 必须所有分支完成
Branches =
{
new InvokeMethod { MethodName = "CheckInventory" },
new InvokeMethod { MethodName = "CheckCredit" }
}
},
// 人工审批(等待审批)
new Pick { ... },
// 处理订单
new If
{
Condition = new InArgument<bool>(isApproved),
Then = new Sequence
{
Activities =
{
new InvokeMethod { MethodName = "ProcessPayment" },
new InvokeMethod { MethodName = "ShipOrder" }
}
},
Else = new WriteLine { Text = "订单审批拒绝" }
}
}
},
Else = new WriteLine { Text = "无效订单!" }
}
}
};八、总结#
WF4.0 的活动模型为构建灵活的企业级工作流提供了强大基础:
- 组合式架构:通过组合简单活动构建复杂业务流程
- 丰富的控制流:Sequence、Flowchart、Parallel等满足不同流程需求
- 声明式编程:通过XAML定义工作流,实现逻辑与表现分离
- 扩展性强:可通过自定义活动扩展功能
在下一篇中,我们将深入探讨自定义活动的开发技术,包括如何创建自定义简单活动和复合活动,以及活动设计器的实现技巧。
九、参考资料#
- 微软官方文档 - WF4 Activities Overview
- Programming Windows Workflow Foundation: Practical WF Techniques
- WF4.0 Activity Library Reference
- Essential Windows Workflow Foundation
- WF4 Samples CodePlex Archive
"工作流不是代码的替代品,而是协调代码执行的艺术" —— WF4.0设计理念