WF 雖非專為企業業務流程(BPM)設計,但其核心優勢在於「流程執行引擎」。企業級 BPM 最複雜的核心正是流程邏輯,因此用 WF 構建 BPM 平台是順勢而為。本文以經典「會簽」流程為例,示範 WF + WCF + WPF 的端到端實作,涵蓋持久化、狀態追蹤、服務化宿主與客戶端呼叫。
發起人發起申請 → 多位會簽人並行/串行審核 → 所有會簽人通過 → 流程結束。任一會簽人駁回 → 流程終止/退回。



WorkflowServiceHost 暴露啟動/處理操作SqlWorkflowInstanceStore 確保流程狀態不丟失



Parallel 活動,每個分支執行「指派任務 → 等待處理 → 記錄結果」FlowDecision 判斷是否全數通過TryCatch 捕獲異常,記錄錯誤狀態,確保持久化一致性// 指派會簽任務活動
public sealed class AssignCountersignTaskActivity : NativeActivity {
[RequiredArgument] public InArgument<Guid> InstanceId { get; set; }
[RequiredArgument] public InArgument<List<string>> Assignees { get; set; }
public OutArgument<List<Guid>> TaskIds { get; set; }
protected override void Execute(NativeActivityContext context) {
var instanceId = InstanceId.Get(context);
var assignees = Assignees.Get(context);
var taskIds = new List<Guid>();
using (var db = new BpmContext()) {
foreach (var user in assignees) {
var task = new CountersignTask {
Id = Guid.NewGuid(), InstanceId = instanceId, Assignee = user,
Status = TaskStatus.Pending, CreatedAt = DateTime.Now
};
db.Tasks.Add(task);
taskIds.Add(task.Id);
}
db.SaveChanges();
}
TaskIds.Set(context, taskIds);
}
}
// 等待會簽處理活動(Bookmark 機制)
public sealed class WaitCountersignActivity : NativeActivity {
[RequiredArgument] public InArgument<Guid> TaskId { get; set; }
public OutArgument<bool> IsApproved { get; set; }
public OutArgument<string> Comment { get; set; }
protected override bool CanInduceIdle => true;
protected override void Execute(NativeActivityContext context) {
var taskId = TaskId.Get(context);
var bookmark = context.CreateBookmark($"Countersign_{taskId}", OnTaskCompleted);
// 此處不阻塞,等待外部 WCF 呼叫 ResumeBookmark
}
void OnTaskCompleted(NativeActivityContext context, Bookmark bookmark, object value) {
var result = (CountersignResult)value;
IsApproved.Set(context, result.IsApproved);
Comment.Set(context, result.Comment);
}
}
[ServiceContract]
public interface ICountersignService {
[OperationContract] Guid StartProcess(StartProcessRequest request);
[OperationContract] void ProcessTask(ProcessTaskRequest request);
[OperationContract] ProcessStatus GetStatus(Guid instanceId);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class CountersignService : ICountersignService {
public Guid StartProcess(StartProcessRequest request) {
var app = new WorkflowApplication(new CountersignFlowchart());
// 設定持久化、追蹤、Extensions...
var instanceId = Guid.NewGuid();
app.Extensions.Add(new BpmContext());
app.Run(instanceId); // 啟動並持久化
return instanceId;
}
public void ProcessTask(ProcessTaskRequest request) {
// 載入流程實例,ResumeBookmark 繼續執行
var store = new SqlWorkflowInstanceStore(connectionString);
var instance = WorkflowApplication.GetInstance(request.InstanceId, store);
var app = new WorkflowApplication(new CountersignFlowchart(), instance.DefinitionIdentity);
app.Extensions.Add(new BpmContext());
app.Load(instance);
app.ResumeBookmark($"Countersign_{request.TaskId}", new CountersignResult {
IsApproved = request.IsApproved, Comment = request.Comment
});
app.Unload(); // 觸發持久化
}
}


private void btnStart_Click(object sender, RoutedEventArgs e) {
var client = new CountersignServiceClient();
var request = new StartProcessRequest {
Title = txtTitle.Text,
Content = txtContent.Text,
Assignees = lstAssignees.Items.Cast<string>().ToList()
};
var instanceId = client.StartProcess(request);
MessageBox.Show($"流程已啟動,InstanceId: {instanceId}");
}
private void btnProcess_Click(object sender, RoutedEventArgs e) {
var client = new CountersignServiceClient();
client.ProcessTask(new ProcessTaskRequest {
InstanceId = Guid.Parse(txtInstanceId.Text),
TaskId = Guid.Parse(txtTaskId.Text),
IsApproved = chkApproved.IsChecked.Value,
Comment = txtComment.Text
});
MessageBox.Show("處理完成");
}








| 技術點 | 實現方式 | 核心價值 |
|---|---|---|
| 長流程持久化 | SqlWorkflowInstanceStore + WorkflowApplication | 應用程式重啟流程不中斷 |
| 外部事件驅動 | Bookmark + WCF ResumeBookmark | 人工任務無縫整合自動化流程 |
| 並行會簽建模 | Parallel 活動 + 動態分支生成 | 天然支援 N 位會簽人並行處理 |
| 狀態可視化 | 自定義追蹤參與者寫入狀態表 | 即時監控、審計追溯、報表分析 |
| 服務化解耦 | WCF 契約隔離 WF 實現細節 | 多種客戶端(Web/Win/WPF/Mobile)統一介面 |
https://files.cnblogs.com/foundation/countersignature.rar
註:本範例專注於 WF 核心流程引擎應用,未包含組織架構、權限系統等 BPM 平台基礎設施,實際專案需補充這些模組。
WF 的價值在於將「流程邏輯」從業務代碼中剝離,成為可視化、可版本化、可持久化、可服務化的獨立資產。會簽只是冰山一角——掌握這套模式,即可應對任意複雜度的長時間業務流程。